Java 容器(三) Set

来源:互联网 发布:2012-2015淘宝交易数据 编辑:程序博客网 时间:2024/05/23 12:18

纸上得来终觉浅

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;}@Overridepublic String toString() {return "Student [id=" + id + ", name=" + name + "]";}@Overridepublic int hashCode() {return this.id;}@Overridepublic boolean equals(Object obj) {if(obj instanceof Student){Student stu = (Student)obj;if(stu.name == this.name)return true;}return false;}@Overridepublic int compareTo(Student o) {return this.id.compareTo(o.id);}}class StudentComparator implements Comparator<Student>{@Overridepublic 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生成方法,改变它的键值区分方式:

@Overridepublic int hashCode() {return this.id;}
再取出,就是:

map:student2

总的来说,使用map的时候,你不把这个对象作为键,就不可以不重写hashcode;但是Set是map实现的,它把对象作为键,那么用set的实现类的时候就要重写hashcode,以实现你想要的效果;

4.总结

1)Set和Map的实现类,其方式都是采用Map,所以都要重写hashcode方法;

2)继承Comparable接口的时候,说明有了排序方法,但只有在支持排序的集合里面才会主动排序,如treeSet,treeMap;Comparator也一样

3)List不支持插入的时候排序,所以list对Comparator和Comparable都支持是通过  Colections.sort,一个list参数代表Comparable排序,两个说明第二个参数是Comparator的实现类。Array同List.
4)linkedHashSet在迭代访问的时候更快,同时记录插入顺序;

0 0