Set集合类似于一个罐子,程序可以依次把多个对象“丢进”Set集合,而Set集合通常不能记住元素的添加顺序。 Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合中,则添加操作失败,add()方法返回 false,且新元素不会被加入。
一:HashSet类是Set接口的典型实现类,大多数时候使用Set集合时就是使用这个实 现类。 HashSet类按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。当向 HashSet集合中存入一个元素时, HashSet会调用该对象的 hashCode()方法来得到该对象的hashCode值,然后根据该hashCode值决定该对 象在HashSet中的存储位置。如果有两个元素通过 equals方法比较返回true,但它们的hashCode()方法返回值不相等, HashSet将会把它们存储在不同的位置, 依然可以添加成功。
HashSet类具有以下特点:
1、不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。
2、HashSet不是同步的(不是线程安全的),如果多个线程同时访问一个 HashSet,假设有两个或者两个以上线程同时修改了 HashSet集合时,则必须通过代码来保证其同步。
3、集合元素值可以是null,但只能放入一个null。
HashSet<String> set = new HashSet<>();
// 添加元素,添加成功时返回true,失败时返回false
set.add("A");
set.add("B");
set.add("C");
set.add("D");
set.add("A");// 添加相同的元素时会添加失败,返回false
set.add(null);// 可以放入null,但只能放入一个null
set.add(null);// 添加相同的元素时会添加失败,返回false
System.out.println("原set集合:" + set);
输出结果如下:
List<String> list = new ArrayList<>();
list.add("F");
list.add("G");
// 批量添加
set.addAll(list);
System.out.println("批量新增之后" + set);
// 移除元素
set.remove("D");
System.out.println("移除元素D之后:" + set);
// 批量移除
set.removeAll(list);
System.out.println("批量移除之后:" + set);
// 转换成字符串之后,输出set
System.out.println("tostring之后:" + set.toString());
输出结果如下:
二:HashSet类还有一个子类 LinkedHashSet, LinkedHashSet集合也是根据元素的 hashCode值来决定元素的存储位置,但它同时使用链表维护元素的次序,这样使得元 素看起来是以插入的顺序保存的。也就是说,当遍历 LinkedhashSet集合里的元素 时, LinkedHashSet将会按元素的添加顺序来访问集合里的元素。 LinkedHashSet需要维护元素的插入顺序,因此性能略低于 HashSet的性能,但 在迭代访问Set里的全部元素时将有很好的性能,因为它以链表来维护内部顺序。
// LinkedHashSet会保持元素的添加顺序
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("A");
set.add("B");
set.add("C");
set.add(null);// 可以放入null,但只能放入一个null
System.out.println(set);
输出结果如下:
三:TreeSet是 SortedSet接口的实现类,正如 SortedSet名字所暗示的, TreeSet可 以确保集合元素处于排序状态,TreeSet 不允许元素为null。
TreeSet<String> set = new TreeSet<>();
set.add("D");
set.add("A");
set.add("C");
set.add("B");
//会自动排序
System.out.println(set);