纸上得来终觉浅
1.这篇说到Set的用法,它的实现类有:
1)HashSet:不重复
2)TreeSet:不重复+主动排序
3)LinkedHashSet:不重复+保持插入时候的顺序
2.下面是具体用法:
package roadArchitectWeb.Test; import java.util.Comparator; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.TreeSet; class Student implements Comparable<Student>{ private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Student(Integer id, String name) { super(); this.id = id; this.name = name; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + "]"; } @Override public int hashCode() { return this.id; } @Override public boolean equals(Object obj) { if(obj instanceof Student){ Student stu = (Student)obj; if(stu.name == this.name) return true; } return false; } @Override public int compareTo(Student o) { return this.id.compareTo(o.id); } } class StudentComparator implements Comparator<Student>{ @Override public int compare(Student o1, Student o2) { return o2.getId().compareTo(o1.getId()); } } public class Test4 { protected static Set<Student> hashSet = new HashSet<Student>(); protected static Set<Student> treeSetComparable = new TreeSet<Student>(); protected static Set<Student> treeSetComparator = new TreeSet<Student>(new StudentComparator()); protected static Set<Student> linkedHashSet = new LinkedHashSet<Student>(); public static void main(String[] args) { hashSet.add(new Student(3,"sun")); hashSet.add(new Student(1,"zhao")); hashSet.add(new Student(2,"qian")); System.out.println("hashSet:"+hashSet); /* *这里使用Comparable */ treeSetComparable.add(new Student(3,"sun")); treeSetComparable.add(new Student(1,"zhao")); treeSetComparable.add(new Student(2,"qian")); System.out.println("treeSetComparable:"+treeSetComparable); /*这里使用Comparator *在讲Arrays的时候已经用了Comparator *如果在treeset中使用的话,就在new Treeset时候传递一个 Comparator的实现类作为参数即可。 */ treeSetComparator.add(new Student(3,"sun")); treeSetComparator.add(new Student(1,"zhao")); treeSetComparator.add(new Student(2,"qian")); System.out.println("treeSetComparator:"+treeSetComparator); linkedHashSet.add(new Student(3,"sun")); linkedHashSet.add(new Student(1,"zhao")); linkedHashSet.add(new Student(2,"qian")); System.out.println("linkedHashSet:"+linkedHashSet); } }3. 三种实现方式都要重写hashcode和equals,为什么?
1)当我们想让对象不重复的进行保存的时候,我们会想到保存到Set里面,这是为什么?
因为Set的实现类提供了对一个对象进行不重复判断的方法,他会根据这个方法来判断两个对象是否一样,这个方法是equals;
2)既然有了equals方法会什么还要重写?
因为每个人认为的相同的标准不一样,equals方法默认方法如下:
public boolean equals(Object obj) { return (this == obj); }它比较的是两个对象的地址是否一样,这样即使两个对象的内容完全一样,但是第二个是new的,也会认为不一样,这个时候如果我想把这两个对象当成一样的来看(这是正常人想法),那么就要重写equals,给他一个新的标准,比如比较两个对象的内容即可,不比较地址:
public boolean equals(Object obj) { if(obj instanceof Student){ Student stu = (Student)obj; if(stu.name == this.name && stu.id == this.id) return true; } return false; }3)重写equals就可以了,为什么还要重写hashcode?
首先要了解hashcode是做什么的? 保存操作,当一个对象作为map的键的时候,Java怎么区分这个键,实际上它是通过键值来区分的,也就是说这个对象作为键,会自动产生一个键值,这个键值是怎么产生的? 就是通过hashcode
HashMap<Student, String> map = new HashMap<Student,String>(); Student student1 = new Student(1, "a"); Student student2 = new Student(2, "a"); Student student3 = new Student(3, "a"); map.put(student1,"student1"); map.put(student2,"student2"); map.put(student3,"student3");那为什么要重写hashcode, 因为默认的hashcode也指的是对象的地址,这样的话如果如果new一个对象,即使值完全一样也是无法取出的,因为地址是新开辟的:
去掉Student中的hashcode方法,然后执行:
HashMap<Student, String> map = new HashMap<Student,String>(); Student student1 = new Student(1, "a"); Student student2 = new Student(2, "a"); Student student3 = new Student(3, "a"); map.put(student1,"student1"); map.put(student2,"student2"); map.put(student3,"student3"); Student student4 = new Student(2, "a"); System.out.println("map:"+map.get(student4));结果是:
map:null
怎么才能取出呢? 那就要改变hashcode生成方法,改变它的键值区分方式:
@Override public int hashCode() { return this.id; }再取出,就是:
map:student2
总的来说,使用map的时候,你不把这个对象作为键,就不可以不重写hashcode;但是Set是map实现的,它把对象作为键,那么用set的实现类的时候就要重写hashcode,以实现你想要的效果;
4.总结
1)Set和Map的实现类,其方式都是采用Map,所以都要重写hashcode方法;
2)数组用Arrays.sort进行排序,且只能用Comparator接口,因为在的初始化是直接初始化,不是一个一个的赋值;
3)继承Comparable接口的时候,说明有了排序方法,但只有在支持排序的集合里面才会主动排序,如treeSet,treeMap;Comparator也一样
4)List不支持插入的时候排序,所以list对Comparator和Comparable都支持是通过 Colections.sort,一个list参数代表Comparator排序,两个说明第二个参数是Comparator的实现类。
5)linkedHashSet在迭代访问的时候更快,同时记录插入顺序;