java笔记之set集合hashset和treeset<四>

---| Set接口     无序,不可以重复的集合  

                            ---| HashSet  线程不安全,存取速度快。底层是以hash表实现的。

                            ---| TreeSet  红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。

1.HashSet

哈希表边存放的是哈希值。HashSet存储元素的顺序并不是按照存入时的顺序(和List显然不同) 是按照哈希值来存的所以取数据也是按照哈希值取得。

HashSet不存入重复元素的规则.使用hashcodeequals

HashSet到底是如何判断两个元素重复。

通过hashCode方法和equals方法来保证元素的唯一性,add()返回的是boolean类型

判断两个元素是否相同,先要判断元素的hashCode值是否一致,只有在该值一致的情况下,才会判断equals方法如果存储在HashSet中的两个对象hashCode方法的值相同equals方法返回的结果是true,那么HashSet认为这两个元素是相同元素只存储一个(重复元素无法存入)。

注意:HashSet集合在判断元素是否相同先判断hashCode方法,如果相同才会判断equals。如果不相同,是不会调用equals方法的。

哈希值相同equalsfalse的元素是怎么存储呢,就是在同样的哈希值下顺延(可以认为哈希值相同的元素放在一个哈希桶中)。也就是哈希一样的存一列。

1hashCode值不相同的情况

2hashCode值相同,但equals不相同的情况。

import java.util.HashSet;
class Emp{
    int id;
    String name;
    int salary;
    public Emp(int id,String name,int salary){
        this.id=id;
        this.name=name;
        this.salary=salary;
    }
    @Override
    public String toString() {
        return "  (编号  "+this.id+" 姓名  "+this.name+" 薪水 "+this.salary+" )  ";
    } 
    @Override
    public int hashCode() {//重写hashcode方法
        return this.id;
    }
    @Override
    public boolean equals(Object obj) {//重写equal方法,判断id和name一致时为true
        if (obj instanceof Emp) {
            Emp emp =(Emp) obj;
            return this.id==id&&this.name.equals(emp.name);
        } else {
                return false;
        }
    }
}

public class hashset02 {
    public static void main(String[] args) {
        HashSet set =new HashSet();
        set.add(new Emp(110, "allen",1000));
        set.add(new Emp(110, "leeleo",1000));
        set.add(new Emp(110, "allen",1000));
        System.out.println("重写方法后输出:"+set);
    }
}

重写方法后输出:[  (编号  110 姓名  allen 薪水 1000 )  ,   (编号  110 姓名  leeleo 薪水 1000 )  ]

此处的set.add(new Emp(110, "allen",1000));和第一次加入对象的hashcode和equal比较后,都返回true。所以就无法存储。把equal方法屏蔽后输出:

[  (编号  110 姓名  allen 薪水 1000 )  ,   (编号  110 姓名  leeleo 薪水 1000 )  ,   (编号  110 姓名  allen 薪水 1000 )  ]

是由于第一次和第三次的hashcode虽然一致,但equal方法未重新,比较的是内存地址,返回的是false。所以可以存储。存储的方式如图二所示。

2.TreeSet

-黑树

红黑树是一种特定类型的二叉树。红黑树算法的规则: 左小右大。既然TreeSet可以自然排序,那么TreeSet必定是有排序规则的。

1:让存入的元素自定义比较规则。

如果元素具备自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。

import java.util.TreeSet;

public class Demo01 {
        public static void main(String[] args) {
            TreeSet set =new TreeSet ();
            set.add(4);
            set.add(2);
            set.add(9);
            set.add(5);
            set.add(8);
            set.add(1);
            System.out.println(set);        
        }
}

输出结果:[1, 2, 4, 5, 8, 9]

2.treeSet添加自定义元素:

treeSet要注意的事项:
1. 往TreeSet添加元素的时候,如果元素本身具备了自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。
2. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,那么该元素所属的类必须要实现Comparable接口,把元素的比较规则定义在compareTo(T o)方法上。 
3. 如果比较元素的时候,compareTo方法返回 的是0,那么该元素就被视为重复元素,不允许添加.(注意:TreeSet与HashCode、equals方法是没有任何关系。)
4. 往TreeSet添加元素的时候, 如果元素本身没有具备自然顺序 的特性,而元素所属的类也没有实现Comparable接口,那么必须要在创建TreeSet的时候传入一个比较器。
5. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,而元素所属的类已经实现了Comparable接口, 在创建TreeSet对象的时候也传入了比较器那么是以比较器的比较规则优先使用。


如何自定义定义比较器: 自定义一个类实现Comparator接口即可,把元素与元素之间的比较规则定义在compare方法内即可


自定义比较器的格式 :

class 类名 implements Comparator{

}
推荐使用:使用比较器(Comparator)。 

 

原文地址:https://www.cnblogs.com/AllenRandolph/p/6952218.html