31.set集合>HashSet--LinkedHashSet--TreeSet
1.Set概述
HashSet
添加元素如果重复会默认覆盖之前的元素:
HashSet hashSet = new HashSet(); hashSet.add("qqq"); hashSet.add("www"); hashSet.add("eee"); hashSet.add("www"); System.out.println(hashSet);//[qqq, eee, www]
HashSet:对集合迭代顺序不作保证:
HashSet hashSet = new HashSet(); hashSet.add("qqq"); hashSet.add("www"); hashSet.add("eee"); System.out.println(hashSet);//[qqq, eee, www]
HashSet保证元素唯一性的源码分析:
注意,是被储存对象对应的类要重写上面的方法:
idea快捷键Alt+Enter:
@Override public boolean equals(Object o) { System.out.println("equals被调用"); if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; if (age != student.age) return false; return name != null ? name.equals(student.name) : student.name == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + age; return result; }
LinkedHashSet
TreeSet
排序就是默认从小到大的排序
自然排序Comparable:
案例:
创建学生类Student实现Comparable并重写CompareTo()方法:
public class Student implements Comparable<Student> { private String name; private int age; ... ... @Override public int compareTo(Student o) { return 0; } }
如果Student没有实现Comparable并重写CompareTo()方法那么下面程序执行就会报错:
如果实现了Comparable并重写CompareTo()方法那么上面程序执行就会打印出如下结果:
从上面结果我们可以看出,只成功添加了一个元素;这是因为CompareTo()方法一直返回的是0: "0代表后面添加的元素和第一个元素比较的时候,前后元素完全一样,所以set就不会添加后面的元素了";因此我们需要重写一下CompareTo()方法:
@Override public int compareTo(Student s) {//重写排序规则 // return 0;//只添加第一个对象,后面对象被视为和第一个对象完全一样而不被添加 // return 1;//(正数)认为前一个对象比后一个对象大 // return -1;//(负数)认为前一个对象比后一个对象小 return this.age-s.age;//结果>0说明上一个学生的年龄大于下一个,就会把大的元素放在后面,然后再和下一个添加元素比较,这样就实现了年龄从小到大的排序 }
但是上面我们仅仅是参照年龄来存储并排序的,年龄相同的人只能存进去一个,是很不合理的,所以我们还要根据姓名字段比较,所以上面代码应该优化为:
public int compareTo(Student s) {//重写排序规则 // return 0;//只添加第一个对象,后面对象被视为和第一个对象完全一样而不被添加 // return 1;//(正数)认为前一个对象比后一个对象大 // return -1;//(负数)认为前一个对象比后一个对象小 int num=this.age-s.age;//结果>0说明上一个学生的年龄大于下一个,就会把大的元素放在后面,然后再和下一个添加元素比较,这样就实现了年龄从小到大的排序 int result=num==0?this.name.compareTo(s.name):num;//年龄不同则返回年龄比较结果,否则返回姓名自然排序结果 return num; }
比较器Comparator:
被操作类Student不需要实现Comparable接口了
public static void main(String[] args) { TreeSet<Student> students = new TreeSet<Student>(new Comparator<Student>() {//使用内部类创建Comparator对象并重写compare方法 @Override public int compare(Student s1, Student s2) { int num=s1.getAge()-s2.getAge(); int result=num==0?s1.getName().compareTo(s2.getName()):num; return result; } }); Student student1 = new Student("刘备", 28); Student student2 =new Student("关于",25); Student student3 =new Student("张飞",29); Student student4 =new Student("马超",27); students.add(student1); students.add(student2); students.add(student3); students.add(student4); Iterator<Student> iterator = students.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } }