• HashSet、HashMap、Hashtable、TreeMap循环、区别


    HashSet 循环

     //可以为null
            HashSet<Object> hashSet =new HashSet<Object>();
            hashSet.add(1);
            hashSet.add("wsss");
            hashSet.add(null);
    
            for (Object s : hashSet) {
                System.out.println(s);
            }
            System.out.println("-----------");
    
            Iterator iterator = hashSet.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }
    
            System.out.println("-----------");
    
            Iterator itor =hashSet.iterator();
            for (Object o : hashSet) {
                if(o instanceof Integer){
                    Integer n =(Integer)o;
                    System.out.println(n);
                }else if(o instanceof String){
                    String str=(String)o;
                    System.out.println(str);
                }else{
                    System.out.println(o);
                }
            }
    HashMap循环
    //可以为null
            HashMap<String,String> hashMap = new HashMap<String,String>();
            hashMap.put("1","zhangsan");
            hashMap.put("4","lisi");
            hashMap.put("7","wangwu");
            hashMap.put(null,null);
    
            Iterator<Map.Entry<String,String>> iterator =hashMap.entrySet().iterator();
            while (iterator.hasNext()){
                Map.Entry<String,String> o =iterator.next();
                System.out.println(o.getKey()+" "+o.getValue());
            }
            System.out.println("-----------");
    
            for (String key : hashMap.keySet()) {
                System.out.println(key+" "+hashMap.get(key));
            }
    
            System.out.println("-----------");
            for (Map.Entry<String, String> entry : hashMap.entrySet()) {
                System.out.println(entry.getKey()+" "+entry.getValue());
            }
            System.out.println("-----------");
            //遍历所有value
            for (String v : hashMap.values()) {
                System.out.println(v);
            }
    Hashtable循环
            //不能为null
            Hashtable<String,String> hashtable=new Hashtable<String,String>();
            hashtable.put("1","zhangsan");
            hashtable.put("2","lisi");
            hashtable.put("3","wangwu");
    
            for (String key:hashtable.keySet()){
                System.out.println(key +" "+hashtable.get(key));
            }
            System.out.println("-----------");
    
            Iterator<Map.Entry<String,String>> iterator = hashtable.entrySet().iterator();
            while (iterator.hasNext()){
                Map.Entry<String,String> itr =iterator.next();
                System.out.println(itr.getKey()+" "+itr.getValue());
            }
    
            System.out.println("-----------");
            for (Map.Entry<String, String> entry : hashtable.entrySet()) {
                System.out.println(entry.getKey()+" "+entry.getValue());
            }

    TreeSet 循环

            //不能为null
            TreeSet<String> treeSet =new TreeSet<String>();
            treeSet.add("zhangsan");
            treeSet.add("ain");
            treeSet.add("wangwu");
    
            Iterator iter = treeSet.iterator();
            while (iter.hasNext()){
                System.out.println(iter.next());
            }

    区别

    1、HashSet实现的是Set接口,HashMap实现的是map接口
    2、HashSet存储的是key,,其实更准确的说是存储一个(key,o),o是HashSet里的一个Object型的成员变量;而HashMap存储的是(key-value);Hashtable窜出的是(key-value);
    3、Hashtable中,key和value都不允许出现null值,HashSet、HashMap都可以为null值
    4、Hashtable中的方法是同步的,而HashMap、HashSet中的方法在缺省情况下是非同步的。
    6、添加元素的时候HashMap、Hashtable使用的是put(key,value),HashSet使用的是add(key);

    -------------------
    TreeSet是一个有序的集合,不允许放入null值,HashSet中的数据是无序的,
    TreeSet采用的数据结构是红黑树,HashSet底层用的是哈希表

    ----------------

    TreeMap 是一个有序的key-value集合,它是通过红黑树实现的。
    TreeMap 继承于AbstractMap,所以它是一个Map,即一个key-value集合。
    TreeMap 实现了NavigableMap接口,意味着它支持一系列的导航方法。比如返回有序的key集合。
    TreeMap 实现了Cloneable接口,意味着它能被克隆。
    TreeMap 实现了java.io.Serializable接口,意味着它支持序列化。
    TreeMap基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
    TreeMap的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n) 。
    另外,TreeMap是非同步的。 它的iterator 方法返回的迭代器是fail-fastl的。

    TreeSet和TreeMap的关系

      与HashSet完全类似,TreeSet里面绝大部分方法都市直接调用TreeMap方法来实现的。

    相同点:

    • TreeMap和TreeSet都是非同步集合,因此他们不能在多线程之间共享,不过可以使用方法Collections.synchroinzedMap()来实现同步
    • 运行速度都要比Hash集合慢,他们内部对元素的操作时间复杂度为O(logN),而HashMap/HashSet则为O(1)。
    • TreeMap和TreeSet都是有序的集合,也就是说他们存储的值都是拍好序的。

    不同点:

    • 最主要的区别就是TreeSet和TreeMap分别实现Set和Map接口
    • TreeSet只存储一个对象,而TreeMap存储两个对象Key和Value(仅仅key对象有序)
    • TreeSet中不能有重复对象,而TreeMap中可以存在
    • TreeMap的底层采用红黑树的实现,完成数据有序的插入,排序。

    什么是HashMap?
    HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干。
    HashMap数组每一个元素的初始值都是Null。
    HashMap是非synchronized;HashMap很快
    HashMap是在bucket中储存键对象和值对象,作为Map.Entry
    HashMap的初始长度是16,并且每次自动扩展或手动初始化时,长度必须是2的幂。

    java7:数组+链表
    java8:数组+链表+红黑树

    java8对hashMap做了什么优化?
    ava7中 hashMap每个桶中放置的是链表,这样当hash碰撞严重时,会导致个别位置链表长度过长,从而影响性能。
    java8中,HashMap 每个桶中当链表长度超过8之后,会将链表转换成红黑树,从而提升增删改查的速度。

    HashMap安排的初始长度,为什么?
    初始长度是 16,每次扩展或者是手动初始化,长度必须是 2的幂。
    因为: index = HashCode(Key) & (length - 1), 如果 length是 2的 幂的话,则 length - 1就是 全是 1的二进制数,比如  16 - 1 = 1111,这样相当于是 坐落在长度为 length的hashMap上的位置只和 HashCode的后四位有关,这只要给出的HashCode算法本身分布均匀,算出的index就是分布均匀的。
    因为HashMap的key是int类型,所以最大值是2^31次方,但是查看源码,当到达 2^30次方,即 MAXIMUM_CAPACITY,之后,便不再进行扩容。


    你知道HashMap的get()方法的工作原理吗?
    HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象.
    使用Get方法根据Key来查找Value的时候,HashMap会使用键对象的hashcode找到bucket位置


    当两个对象的hashcode相同会发生什么?
    因为hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。因为HashMap使用LinkedList存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在LinkedList中

    如果两个键的hashcode相同,你如何获取值对象?
    当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,找到bucket位置之后,会调用keys.equals()方法去找到LinkedList中正确的节点,最终找到要找的值对象

    如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?
    默认的负载因子大小为0.75,也就是说,当一个map填满了75%的bucket时候,和其它集合类一样,将会创建原来HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程叫作(再散列)rehashing,因为它调用hash方法找到新的bucket位置。

    可以使用自定义的对象作为键吗?
    可以使用任何对象作为键,只要它遵守了equals()和hashCode()方法的定义规则,并且当对象插入到Map中之后将不会再改变了。如果这个自定义对象时不可变的,那么它已经满足了作为键的条件,因为当它创建之后就已经不能改变了。

    可以使用CocurrentHashMap来代替HashTable吗?
    HashTable是synchronized的,但是ConcurrentHashMap同步性能更好,因为它仅仅根据同步级别对map的一部分进行上锁。ConcurrentHashMap当然可以代替HashTable,但是HashTable提供更强的线程安全性。

    为什么String, Interger这样的wrapper类适合作为键?
    因为String是不可变的,也是final的,而且已经重写了equals()和hashCode()方法了。其他的wrapper类也有这个特点。不可变性是必要的,
    因为为了要计算hashCode(),就要防止键值改变,如果键值在放入时和获取时返回不同的hashcode的话,那么就不能从HashMap中找到你想要的对象。不可变性还有其他的优点如线程安全。如果你可以仅仅通过将某个field声明成final就能保证hashCode是不变的,那么请这么做吧。因为获取对象的时候要用到equals()和hashCode()方法,那么键对象正确的重写这两个方法是非常重要的。如果两个不相等的对象返回不同的hashcode的话,那么碰撞的几率就会小些,这样就能提高HashMap的性能。

  • 相关阅读:
    CF1435E Solo mid Oracle(推柿子)
    CF1435C Perform Easily(Set)
    NC7501I (反向建图)
    NC7501D Router Mesh (去掉割点算连通快的变化)
    超全的Python第三方库
    字符串常见题目
    IDEA的常用设置大全
    IDEA的介绍与安装
    涨姿势啦(1)
    Torch常用的函数总结
  • 原文地址:https://www.cnblogs.com/puke/p/8664233.html
Copyright © 2020-2023  润新知