collection集合--set

Set(无序、不能重复)

通过元素的equals方法,来判断是否为重复元素,

Lis是存放有序的,可重复的;

Set里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中。

不能存储相同的元素。

 Set集合由Set接口和Set接口的实现类组成

同时因为其是一个抽象的接口:所以不能直接实例化一个set对象。(Set s = new Set() )错误

该接口主要继承于Collections接口,所以具有Collection的一些常见的方法。

 Set接口继承了Collection接口,因此包含Collection接口的所有方法

(Set 的构造有一个约束条件,传入的Collection对象不能有重复)

 

Set 接口常用的实现类 有 HashSet 类 与LinkedHashSet

 

HashSet:为快速查找设计的Set。存入HashSet的对象必须必须重写:hashCode()与equals()方法

 

 

 为什么重写hascode和equals:

1.Set不存重复元素

2.让equals方法和hashCode方法始终在逻辑上保持一致性。

其底层实现是一个哈希表,存入HashSet中的元素没有顺序性。它不保证Set的迭代顺序,特别是它不保证该顺序恒久不变,此类允许使用 null 元素

程序向HashSet中添加一个对象时,先用hashCode方法计算出该对象的哈希码。比较:

(1),如果该对象哈希码与集合已存在对象的哈希码不一致,则该对象没有与其他对象重复,添加到集合中!

(2),如果存在于该对象相同的哈希码,那么通过equals方法判断两个哈希码相同的对象是否为同一对象(判断的标准是:属性是否相同)

1>,相同对象,不添加。

2>,不同对象,添加!

这时有两个疑问:1,为什么哈希码相同了还有可能是不同对象?2,为什么经过比较哈希码还需要借助equals方法判断?

 

答:首先:按照Object类的hashCode方法,是不可能返回两个相同的哈希码的。(哈希码唯一标志了对象) 然后:Object类的hashCode方法返回的哈希码具有唯一性(地址唯一性),但是这样不能让程序的运行逻辑符合现实生活。(这个逻辑就是:属性相同的对象被看作同一个对象。)为了让程序的运行逻辑符合现实生活,Object的子类重写了hashCode的方法(基本数据类型的实现类都已经重写了两个方法,自定义的类要软件工程 师自己重写。)

个人理解:

add()方法先调用hashCode方法进行比较,结果为相同对象在调用eques()方法比较

 

那么:重写的宗旨是什么?重写就是为了实现这样的目的:属性相同的不同对象在调用其hashCode方法后,返回的是同样的哈希码。但是我们在重写的时候,发现几乎所有的写法都无法避免一个bug:有一些属性不同的对象(当然是不同的对象),会返回相同的哈希码。(即 重码)

 

最后:为了解决这个问题:在哈希码相同的时候,再用equals方法比较两个对象的对应属性是否相同,这样,确保了万无一失。这样:上面两个问题得到解决。

原文链接:https://blog.csdn.net/qq_38704184/article/details/81511695

LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。

存入和取出的顺序一致(有序)

 

HashSet

哈希表如何确定元素是否相同?

  1. 判断两个元素的哈希值是否相同,其实判断的是对象的 hashCode() 方法
  2. 如果哈希值相同,再判断两个对象的内容是否相同,用的是 equals() 方法
  3. 如果哈希值不同,是不需要判断 equals() 方法的

  

HashSet是基于HashMap来实现的,操作很简单,更像是对HashMap做了一次“封装”,而且只使用了HashMap的key来实现各种特性,而HashMap的value始终都是PRESENT。

HashSet不允许重复(HashMap的key不允许重复,如果出现重复就覆盖),允许null值,非线程安全。

HashSet:

,(哈希值存入数组,链表存元素)

                   *当我们向集合 中存元素时,Add方法先去调用集合存储的类型的类中的hashcode

                   *方法计算该元素的哈希值,计算结束去寻找是否有该哈希值,如果没有,直接存如该元素到集合中。如果有,则调用该类型的

                   *eques方法比较内容,如果内容不相同,将该元素存入集合链表中,如果相同,则不存。。相同哈希值,则挂到最下面

 

构造方法

HashSet()
  构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。
HashSet(Collection<? extends E> c)
  构造一个包含指定 collection 中的元素的新 set。
HashSet(int initialCapacity)
  构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。
HashSet(int initialCapacity, float loadFactor)
  构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和指定的加载因子。

方法

boolean add(E e)
  如果此 set 中尚未包含指定元素,则添加指定元素。
void clear()
  从此 set 中移除所有元素。
** Object clone()
  返回此 HashSet 实例的浅表副本:并没有复制这些元素本身。
boolean contains(Object o)
  如果此 set 包含指定元素,则返回 true。
boolean isEmpty()**
  如果此 set 不包含任何元素,则返回 true。
** Iterator iterator()
  返回对此 set 中元素进行迭代的迭代器。
boolean remove(Object o)
  如果指定元素存在于此 set 中,则将其移除。
int size()**
  返回此 set 中的元素的数量(set 的容量)。

遍历(和list相似)

set 的遍历

    迭代遍历:

Set<String> set = new HashSet<String>(); 

Iterator<String> it = set.iterator(); 

while (it.hasNext()) { 

  String str = it.next(); 

  System.out.println(str); 

}  

 

 

2.增强for

3.HashSet

public static void main(String[] args) {

     Set<String> set =new  HashSet<String>();

     set.add("abc");

     set.add("bcd");

     set.add("abc");

  for(String s:set) {

     System.out.println(s);   

  }//结果bcd,abc

  }

 

 

package com.oracle.Demo02;

 

import java.util.HashSet;

import java.util.Set;

 

public class demo02 {

 

         public static void main(String[] args) {

                   /*int s1="abc".hashCode();

                   int s2="abc".hashCode();

                   int s3="bcd".hashCode();

                   *,(哈希值存入数组,链表存元素)

                   *当我们向集合 中存元素时,Add方法先去调用集合存储的类型的类中的hashcode

                   *方法计算该元素的哈希值,计算结束去寻找是否有该哈希值,如果没有,直接存如该元素到集合中。如果有,则调用该类型的

                   *eques方法比较内容,如果内容不相同,将该元素存入集合链表中,如果相同,则不存。。相同哈希值,则挂到最下面

                   System.out.println(s1);

                   System.out.println(s2);

                   System.out.println(s3);*/

                  

                   Set<Person> set =new  HashSet<Person>();

                    set.add(new Person("a",10));

                    set.add(new Person("b",9));

                    set.add(new Person("a",8));

                     for(      Person p:set) {

                              System.out.println(p);

                     }

                    /*

                     Person [name=熊二, age=28]

          Person [name=熊大, age=18]

          Person [name=熊大, age=18]

          不重写hashcode,调用

          重复元素

   

         }

 

}

 

posted @ 2019-08-31 09:58  腊月出去玩  阅读(256)  评论(0编辑  收藏  举报