zoukankan      html  css  js  c++  java
  • 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,调用
    
              重复元素
    
       
    
             }
    
     
    
    }
  • 相关阅读:
    hdu 2553 N皇后问题(dfs)
    hdu 1043 Eight(双向bfs)
    牛人的ACM经验 (转)
    康托和逆康托展开(转)
    hiho Mission Impossible 6(模拟 未提交验证。。)
    数组越界也可以这么巧~~~
    poj 1679 The Unique MST(次小生成树)
    zoj 3204 Connect them(最小生成树)
    hdu 4463 Outlets(最小生成树)
    廖雪峰Java1-2程序基础-8字符和字符串
  • 原文地址:https://www.cnblogs.com/layuechuquwan/p/11438030.html
Copyright © 2011-2022 走看看