文章目录
- Set
- HashSet
- TreeSet
- Set 和 List 的区别
- Iterator接口
- Collections 工具类
Set
介绍
Set 继承于 Collection 接口,是一个不允许出现重复元素,并且无序的集合,主要有 HashSet 和 TreeSet 两大实现类。
Set 常用方法
与 List 接口一样,Set 接口也提供了集合操作的基本方法。
但与 List 不同的是, Set 还提供了 equals(Object o)和 hashCode(),供其子类重写,以实现对集合中插入重复元素的处理。
public interface Set<E> extends Collection<E> {
A:添加功能
boolean add(E e);
boolean addAll(Collection<? extends E> c);
B:删除功能
boolean remove(Object o);
boolean removeAll(Collection<?> c);
void clear();
C:长度功能
int size();
D:判断功能
boolean isEmpty();
boolean contains(Object o);
boolean containsAll(Collection<?> c);
boolean retainAll(Collection<?> c);
E:获取Set集合的迭代器:
Iterator<E> iterator();
F:把集合转换成数组
Object[] toArray();
<T> T[] toArray(T[] a);
//判断元素是否重复,为子类提高重写方法
boolean equals(Object o);
int hashCode();
}HashSet
HashSet 内部封装 HashMap 对象,使用 HashMap 的键这一列来存放对象,里边的数据不重复且无序。
当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的hashCode方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。如果有两个元素通过equals方法比较 true,但它们的hashCode方法返回的值不相等,HashSet 将会把它们存储在不同位置,依然可以添加成功。也就是说。 HashSet 集合判断两个元素的标准是两个对象通过 equals 方法比较相等,并且两个对象的 hashCode 方法返回值也相等。
靠元素重写 hashCode 方法和 equals 方法来判断两个元素是否相等,如果相等则覆盖原来的元素,依此来确保元素的唯一性。
创建对象
HashSet set = new HashSet();hashset 特点
1、不允许出现重复因素;
2、允许插入Null值;
3、元素无序(添加顺序和遍历顺序不一致);
4、线程不安全,若2个线程同时操作HashSet,必须通过代码实现同步;
举例:HashSet 练习
public class Main {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(99);
set.add(55);
set.add(77);
set.add(44);
set.add(88);
set.add(11);
set.add(33);
System.out.println(set.size());//7
System.out.println(set);//[33, 99, 55, 88, 11, 44, 77]
System.out.println(set.contains(99));//true
System.out.println(set.remove(44));//true
System.out.println(set);//[33, 99, 55, 88, 11, 77]
//迭代器遍历
Iterator<Integer> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//遍历结果:
/*33
99
55
88
11
77*/
//迭代器的另一种写法
for (Iterator<Integer> it2 = set.iterator(); it2.hasNext(); ) {
System.out.println(it2.next());
}
}
}
由于Set集合中并没有角标的概念,所以并没有像 List 一样提供 get() 方法。当获取 HashSet 中某个元素时,只能通过遍历集合的方式进行 equals() 比较来实现;
TreeSet
介绍
内部封装 TreeMap 对象,使用 TreeMap 的键这一列来存放对象,数据不重复有序。
与 HashSet 不同的是,TreeSet 具有排序功能,分为自然排序(123456)和自定义排序两类,默认是自然排序;在程序中,我们可以按照任意顺序将元素插入到集合中,等到遍历时 TreeSet 会按照一定顺序输出–倒序或者升序。
TreeSet 特点
1、对插入的元素进行排序,是一个有序的集合(主要与HashSet的区别);
2、底层使用红黑树结构,而不是哈希表结构;
3、允许插入Null值;
4、不允许插入重复元素;
5、线程不安全;
创建对象
TreeSet set = new TreeSet();
TreeSet set = new TreeSet(比较器);举例:关键词去重
例如输入关键词:
aaa,aaa,bbb,ccc,ccc
返回去除重复的关键词后:
aaa,bbb,ccc
public class Main {
public static void main(String[] args) {
System.out.println("输入关键词列表,用逗号隔开");
String s = new Scanner(System.in).nextLine();
//aa,aa,bb,cc,cc
String[] a = s.split(",");
Set<String> set = new TreeSet<>();
for (int i = 0; i < a.length; i++) {
set.add(a[i]);
}
for (Iterator<String> it = set.iterator(); it.hasNext(); ) {
System.out.println(it.next());
}
}
}运行结果:
与HashSet集合相比,TreeSet还提供了几个额外方法:
Comparator comparator():如果TreeSet采用了定制顺序,则该方法返回定制排序所使用的Comparator,如果TreeSet采用自然排序,则返回null;
Object first():返回集合中的第一个元素;
Object last():返回集合中的最后一个元素;
Object lower(Object e):返回指定元素之前的元素。
Object higher(Object e):返回指定元素之后的元素。
SortedSet subSet(Object fromElement,Object toElement):返回此Set的子集合,含头不含尾;
SortedSet headSet(Object toElement):返回此Set的子集,由小于toElement的元素组成;
SortedSet tailSet(Object fromElement):返回此Set的子集,由大于fromElement的元素组成举例:TreeSet 使用练习
TreeSet<String> treeSet = new TreeSet<>();
System.out.println("TreeSet初始化容量大小:" + treeSet.size());//0
//元素添加:
treeSet.add("my");
treeSet.add("name");
treeSet.add("is");
treeSet.add("Errol");
treeSet.add("1");
treeSet.add("2");
treeSet.add("3");
System.out.println("TreeSet容量大小:" + treeSet.size());//7
System.out.println("TreeSet元素顺序为:" + treeSet);//[1, 2, 3, Errol, is, my, name]
//增加for循环遍历:
for (String str : treeSet) {
System.out.println("遍历元素:" + str);
}
//迭代器遍历:升序
Iterator<String> iteratorAesc = treeSet.iterator();
while (iteratorAesc.hasNext()) {
String str = iteratorAesc.next();
System.out.println("遍历元素升序:" + str);
}
//迭代器遍历:降序
Iterator<String> iteratorDesc = treeSet.descendingIterator();
while (iteratorDesc.hasNext()) {
String str = iteratorDesc.next();
System.out.println("遍历元素降序:" + str);
}
System.out.println("TreeSet头节点为:" + treeSet.first());//1
// 获取指定元素之前的所有元素集合:(不包含指定元素)
SortedSet<String> headSet = treeSet.headSet("is");
System.out.println("is节点之前的元素为:" + headSet.toString());//[1, 2, 3, Errol]
//获取给定元素之间的集合:(包含头,不包含尾)
SortedSet subSet = treeSet.subSet("3", "my");
System.out.println("3-my之间节点元素为:" + subSet.toString());//[3, Errol, is]
//集合判断:
System.out.println("TreeSet是否为空:" + treeSet.isEmpty());//false
System.out.println("TreeSet是否包含name元素:" + treeSet.contains("name"));//true
//元素删除:
System.out.println("3元素是否被删除" + treeSet.remove("3"));//true
//集合中不存在的元素,删除返回false
System.out.println("who元素是否被删除" + treeSet.remove("who"));//false
//删除并返回第一个元素:如果set集合不存在元素,则返回null
System.out.println("删除的第一个元素:" + treeSet.pollFirst());//1
//删除并返回最后一个元素:如果set集合不存在元素,则返回null
System.out.println("删除的最后一个元素:" + treeSet.pollLast());//name
//清空集合
treeSet.clear();其余打印都写在注释中了,循环遍历的结果如下:
遍历元素:1
遍历元素:2
遍历元素:3
遍历元素:Errol
遍历元素:is
遍历元素:my
遍历元素:nameSet 和 List 的区别
- Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
- Set 检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。 <实现类有 HashSet,TreeSet >。
- List 和数组类似,可以动态增长,根据实际存储的数据的长度自动增长 List 的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变。<实现类有ArrayList,LinkedList,Vector> 。
Iterator接口
Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法。一般遍历数组都是采用 for 循环或者增强 for,这两个方法也可以用在集合框架,但我们也可以采用迭代器遍历集合框架,实现了 Iterator 接口或 ListIterator 接口。可用于迭代 ArrayList 和 HashSet 等集合。
方法
hasNext()//用于检测集合中是否还有元素
next()//返回迭代器的下一个元素,并且更新迭代器的状态。
remove()//将迭代器返回的元素删除。
我们之前的代码中也用到了,现在再举个例子看一下
List<String> list=new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("!");
Iterator<String> it = list.iterator();
//判断下一个元素之后是否有值
while(it.hasNext()){
System.out.println(it.next());
}运行结果如下:
Hello
World
!
iterator 和 for 循环的区别
从数据结构角度分析,for 循环适合访问顺序结构,可以根据下标快速获取指定元素。而 Iterator 适合访问链式结构,因为迭代器是通过 next() 来定位的,可以访问没有顺序的集合。
Collections 工具类
集合之 LinkedList中我们提到了 Collection。
排序操作
Collections 提供以下方法对 List 进行排序操作
void reverse(List list):反转
void shuffle(List list):随机排序
void sort(List list):按自然排序的升序排序
void sort(List list, Comparator c):定制排序,由 Comparator 控制排序逻辑
void swap(List list, int i , int j):交换两个索引位置的元素
void rotate(List list, int distance):旋转。当 distance 为正数时,将 list 后 distance 个元素整体移到前面。当 distance 为负数时,将 list 的前 distance 个元素整体移到后面。
查找,替换操作
int binarySearch(List list, Object key) :对 List 进行二分查找,返回索引,注意 List 必须是有序的
int max(Collection coll):根据元素的自然顺序,返回最大的元素。 类比 int min(Collection coll)
int max(Collection coll, Comparator c):根据定制排序,返回最大元素,排序规则由 Comparatator 类控制。类比 int min(Collection coll, Comparator c)
void fill(List list, Object obj):用元素 obj 填充 list 中所有元素
int frequency(Collection c, Object o):统计元素出现次数
int indexOfSubList(List list, List target):统计 targe 在 list 中第一次出现的索引,找不到则返回 -1,类比 int lastIndexOfSubList(List source, list target).
boolean replaceAll(List list, Object oldVal, Object newVal) :用新元素替换旧元素
addAll(Collection,值1,值2,值3...):向指定集合,加入多个数据
栗子
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Collections.addAll(
list,
"8",
"11",
"5",
"4364",
"8",
"215",
"21",
"41029",
"20",
"6",
"1162");
System.out.println(list);
System.out.println("-----------");
Collections.sort(list);
System.out.println(list);
}输出结果
[8, 11, 5, 4364, 8, 215, 21, 41029, 20, 6, 1162]
[11, 1162, 20, 21, 215, 41029, 4364, 5, 6, 8, 8]
虽然已经排序了,但是排序是根据字符串排序的,并不是按照数字从小到大排序的,如果需要按照数字从小到大排序,可以外接一个比较器
//外接比较器
Collections.sort(list,new Comparator<String>(){
public int compare(String arg0, String arg1) {
int a = Integer.parseInt(arg0);
int b = Integer.parseInt(arg1);
//为了防止溢出,直接用大小比较
if(a>b){
return 1;
}else if(a<b){
return -1;
}else{
return 0;
}
}
});
System.out.println(list);输出结果
[5, 6, 8, 8, 11, 20, 21, 215, 1162, 4364, 41029]
参考
Java中的Set总结java中的Set集合JAVA基础知识之Collections工具类










