15 Set集合
set集合特点:
Set类似一个罐子,一旦把对象丢进Set集合,集合中多个对象之间没有明显的顺序。Set集合与Collection基本上完全一样,他没有提供任何额外的方法,实际上Set就是Collection,只是行为不同(Set不能存储重复元素)
Set 判断两个对象相同不是使用==运算符,而是根据equals方法,也就是说,如果只要两个对象用equals方法比较返回true,Set就不会接受者两个对象,反之,只要两个对象用equals方法比较返回false,Set就会接受这两个对象(甚至这两个对象是同一个对象,Set也可把它们当成两个对象处理。)
Set集合的通用知识
//创建集合对象
Set<String> set=new HashSet<>();
//添加元素
set.add("1");
set.add("2");
set.add("3");
set.add("4");
set.add("5");
set.add("6");
set.add("7");
set.add("9");
set.add(new String("9"));
//不保证存入顺序
System.out.println(set);//[1, 2, 3, 4, 5, 6, 7, 9]
System.out.println(set.size());//8
实现类:HashSet、LinkedHaset,TreeSet
HashSet类
一个桶可以存放多个元素
如果已经存储元素的桶数/总桶数大于加载因子(默认是0.75),表明此数组需要进行扩容,默认扩容一倍,每次扩容之后要重新计算我们每个元素的哈希码值,进行重新分配,保证元素平均分配在桶中--(这个过程就是rehash)
HashSet底层是由数组和链表(单向链表不是linkedlist)实现的
值得主要的是,HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法的返回值相等
HashSet具有以下特点
1.不能存储重复元素,不能保证元素的排列顺序,顺序有可能发生变化
2.底层数组长度一定是2的n次方。
3.HashSet不是同步的,如果多个线程同时访问一个HashSet,如果有两条或者2条以上的线程同时修改了HashSet集合时,必须通过代码来保证其同步
4.集合元素值可以是null.
当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该HashCode值来决定该对象在HashSet中存储位置。如果有两个元素通过equals方法比较返回true,但它们的hashCode()方法返回值不相等,HashSet将会把它们存储在不同位置,也就可以添加成功
简单来说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值也相等
如果需要把一个对象放入HashSet中时,如果重写该对象对应类的equals()方法,也应该重写其hashCode()方法,其规则是:如果2个对象通过equals方法比较返回true时,这两个对象的hashCode也应该相同
加载因子越小,会频繁进行扩容操作,导致大量的桶没有进行存储,内存空间浪费,需要进行频繁的rehash操作降低工作效率
加载因子越大,链式栈结构的长度,导致查询效率降低
如果链式栈结构的长度超过8个,从JDK1.8开始把这个链式结构就扭转成一个二叉树进行存储(时间复杂度优化(0(N)---0(log2n))
TreeSet
会自动对存储的元素进行排序---升序---自然排序
如果是对象存储在TreeSet中想要进行排序,保证对象对应的类实现Comparable接口,重写compareTo去重写比较方法
public static void main(String[] args) { /* //创建集合对象 TreeSet<String> set = new TreeSet<>( ); //添加元素 set.add( "234" ); set.add( "12" ); set.add( "4" ); set.add( "2" ); set.add( "34" ); //自动排序 System.out.println(set);*/ //创建 TreeSet<Person> set = new TreeSet<>( ); //添加元素---Person类对象 set.add( new Person( "关羽",35,89 ) ); set.add( new Person( "张飞",34,9 ) ); set.add( new Person( "诸葛亮",30,120 ) ); set.add( new Person( "赵云",28,99 ) ); // System.out.println(set); }优质内容筛选与推荐>>
//想要让对象进行自动排序 --- 要实现Comparable 接口 class Person implements Comparable<Person>{ String name; int age; int score;//对分数进行排序 //给对象属性进行赋值 public Person(String name,int age,int score){ this.name = name; this.age = age; this.score = score; } //重写toString @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + '}'; } //指定我们具体的比较规则 @Override public int compareTo(Person o) { //指定排序规则 //如果返回的值是正数,说明前面的对象大于后面的对象 //如果返回的是负数,说明前面的对象小于后面的对象 //如果返回的是0,说明两个对象相等 return this.score - o.score;//分数升序 } }