set
-
set接口用于存储无序并且元素不可重复的集合,如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3e4grplS-1599911871739)(D:\downfile\QQ\tu2.png)]
-
set接口常用的实现子类有HashSet、LinkedHashSet、TreeSet类等。
1 HashSet
-
HashSet是set集合中最常用的实现类,HashSet是按照哈希算法来存储的,因此具有很好的存取和查找性能。
-
HashSet特点:
- 无序,不能保证元素的顺序
- HashSet不是线程同步的,如果多线程操作HashSet集合,则应通过代码来实现线程同步。
- 集合元素可以为null
-
案例1:
public class Test { public static void main(String[] args) { HashSet dest = new HashSet(); dest.add(1); dest.add(71); dest.add(23); dest.add(67); dest.add(98); for (Object object : dest) { System.out.print(" "+object); } System.out.println("\n==========================="); //因为此循环是无序的,我们不能通过for循环遍历该集合 //我们可以通过迭代器让无序的集合"排队" Iterator it = dest.iterator(); while (it.hasNext()) { Object obj = it.next(); System.out.print(" "+obj); } } }
-
结果
1 98 67 71 23 =========================== 1 98 67 71 23
-
案例2:
import java.util.HashSet; public class Test02 { public static void main(String[] args) { Student stu1 = new Student("马云",45,'男'); Student stu2 = new Student("马化腾",46,'男'); Student stu3 = new Student("董明珠",47,'女'); Student stu4 = new Student("章泽天",28,'女'); HashSet<Student> dest = new HashSet<Student>(); dest.add(stu1); dest.add(stu2); dest.add(stu3); dest.add(stu4); for (Student student : dest) { student.showStudent(); } } }
-
结果
你好我是董明珠年龄:47性别:女 你好我是马云年龄:45性别:男 你好我是马化腾年龄:46性别:男 你好我是章泽天年龄:28性别:女
2 LinkedHashSet
-
LinkedHashSet是介于HashSet和TreeSet之间,内部是一个双向链表结构,所以它插入是有序的。linkedHashSet是HashSet的一个子类,具有HashSet的特性,也是根据元素的HashCode值来决定元素的存储位置。但它使用链表维护元素的次序,元素的顺序与添加顺序一致,由于LinkedHashSet需要维护元素的插入顺序,因此性能上略低于Hashset,但在迭代访问Set里面的全部元素时候由有很好的性能。
-
案例
import java.util.Iterator; import java.util.LinkedHashSet; public class Test { public static void main(String[] args) { //以链表式和Hash算法相结合,插入有序的set集合 LinkedHashSet lset = new LinkedHashSet(); lset.add(1); lset.add(4); lset.add(7); lset.add(2); lset.add(5); lset.add(8); for (Object object : lset) { System.out.print(" " + object); } System.out.println("\n======================"); Iterator it = lset.iterator(); while (it.hasNext()) { Object obj = it.next(); System.out.print(" "+obj); } } }
-
结果
1 4 7 2 5 8 ====================== 1 4 7 2 5 8
3 TreeSet
-
TreeSet是sortedSet接口的实现类,TreeSet可以保证元素处于排序状态,它采用的是红黑树算法的数据结构来存储集合元素.TreeSet支持两种排序方法:自然排序和定制排序,默认采用自然排序。
-
案例:
import java.util.Iterator; import java.util.TreeSet; public class Test { public static void main(String[] args) { TreeSet tree = new TreeSet(); tree.add(1); tree.add(41); tree.add(54); tree.add(32); tree.add(4); tree.add(52); Iterator<Integer> it = tree.iterator(); while (it.hasNext()) { Integer val = it.next(); System.out.print(" "+val); } } }
-
结果:会自然排序插入到集合中
1 4 32 41 52 54
-
自然排序
TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素的大小,然后将元素按照升序排序,这就是自然排序。
-
定制排序
1.如果Treeset集合插入的是对象,那么对象是无法去比较排序的,所以我们需要通过定制排序来定制对象之间排序的规则。 2.需要在创建TreeSet集合对象时,提供一个comparator对象与该TreeSet集合关联,由comparator对象负责集合元素的排序规则。
-
实现步骤:
-
在集合的元素的类里面实现comparator接口
public class Student implements Comparable<Student>{ private String name; private int age; public void showStudent(){ System.out.println("你好我是"+name+",年龄是:"+age); } public Student() { super(); } public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } /** * 重写compareTo方法,自定义比较规则 * 如果两个对象的值相等返回0 * obj1对象大于obj2对象返回正数 * obj1对象小于obj2对象返回负数 * 返回的结果不需要关心,你只需要返回正数、负数、0这三种结果即可,底层其它方法根据你的结果去比较排序 */ @Override public int compareTo(Student stu) { int num = this.age-stu.age; return num; } }
-
重写compareto(Object obj)方法自定义排序规则
import java.util.TreeSet; public class Test1 { public static void main(String[] args) { Student stu1 = new Student("马云",45); Student stu2 = new Student("马化腾",40); Student stu3 = new Student("董明珠",47); Student stu4 = new Student("章泽天",28); TreeSet<Student> tree = new TreeSet<Student>(); tree.add(stu1); tree.add(stu2); tree.add(stu3); tree.add(stu4); for (Student student : tree) { student.showStudent(); } } }
-
结果
你好我是章泽天,年龄是:28 你好我是马化腾,年龄是:40 你好我是马云,年龄是:45 你好我是董明珠,年龄是:47
-
4 EnumSet
- EnumSet是一个专门用来存放枚举类型的集合,不允许添加null值。EnumSet集合元素也是有序的,它是以枚举值在Enum类内的定义顺序来决定集合元素的顺序。
5 各set集合实现类的性能分析
- HashSet的性能比TreeSet性能好,因为TreeSet需要额外通过红黑树算法来维护元素次序,如果需要保持一个排序的set时候用TreeSet,否则应该使用HashSet
- LinkedHashSet是HashSet的子类,由于需要维护链表的顺序,所以插入和删除操作比HashSet要慢,但遍历比Hashset要快
- EnumSet是所有实现类中性能最慢的,但它只能用于保存同一个枚举类的枚举值作为元素的集合。
- 以上几个Set实现类都是非线程安全的,如果需要多线程访问,必须手动包装集合的同步性。
- 必须学会:ArrayList、LInkedList、hashSet
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student("马云",45);
Student stu2 = new Student("马化腾",46);
Student stu3 = new Student("董明珠",47);
Student stu4 = new Student("章泽天",28);
Map<String,Student> map = new Hashtable<String,Student>();
map.put(stu1.getName(), stu1);
map.put(stu2.getName(), stu2);
map.put(stu3.getName(), stu3);
map.put(stu4.getName(), stu4);
//map转换list
List<Student> list = CollectionUtils.getMapTranToList(map);
for (Student student : list) {
student.showStudent();
}
}
}