首页 > 其他 > 详细

HashSet TreeSet Map

时间:2021-05-30 15:47:07      阅读:18      评论:0      收藏:0      [点我收藏+]

 

HashSet

无序不可重复:

  • 存储是顺序和取出的顺序不同,

  • 不可重复

  • 放到HashSet集合中的元素实际上是放到了HashMap集合的key部分了

技术分享图片

TreeSet集合

  • 无序不可重复的但是存储的元素可以自动按照大小顺序来排序

    • 称为:可排序集合。

  • 无序:指的是存进去的顺序和取出来的顺序不同 并且没有下标

  • 技术分享图片

  • 技术分享图片

<> 泛型 集合中元素更加统一,让我们写代码的时候很少再进行向下转型

增强for循环 foreach 不带下标

 

 

Map

map接口中常用的方法:

  • Map 和Collection没有继承关系

  • Map集合以key和value的方式存储数据:键值对

    • key和value都是引用数据类型

    • key和value都是存储对象的内存地址。

    • key起主导地位,value是key的一个附属品

  • Map中常用的方法:

 

    •  

      void**[clear](../../java/util/Map.html#clear())**() 从此映射中移除所有映射关系(可选操作)。清空Map集合
      boolean **[containsKey](../../java/util/Map.html#containsKey(java.lang.Object))**(Object key) 如果此映射包含指定键的映射关系,则返回 true 判断Map中是否包含某些个key
      boolean **[containsValue](../../java/util/Map.html#containsValue(java.lang.Object))**(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true 是否包含某些个value
      Set<Map.Entry<K,V>> **[entrySet](../../java/util/Map.html#entrySet())**() 返回此映射中包含的映射关系的 Set 视图。 将Map集合转换成Set集合
      boolean **[equals](../../java/util/Map.html#equals(java.lang.Object))**(Object o) 比较指定的对象与此映射是否相等。  
      V **[get](../../java/util/Map.html#get(java.lang.Object))**(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null 通过key获取value
      int **[hashCode](../../java/util/Map.html#hashCode())**() 返回此映射的哈希码值。  
      boolean **[isEmpty](../../java/util/Map.html#isEmpty())**() 如果此映射未包含键-值映射关系,则返回 true Map集合中元素个数是否为0
      Set<K> **[keySet](../../java/util/Map.html#keySet())**() 返回此映射中包含的键的 Set 视图。 获取所有的key
      V **[put](../../java/util/Map.html#put(K, V))**(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。 向Map集合中添加键值对
      • Set< >

      • 【注意】:Map集合通过entrySet()方法转换成的这个Set集合,Set集合中元素的类型是Map.Entry<k,v>

      • 【Map.entry 和String 一样,都是一种类型的名字,只不过:Map.entry 是一种静态内部类,是Map中的静态内部类】

技术分享图片


技术分享图片

技术分享图片

技术分享图片


get put remove clear contains values

?
package com.zhang.san;
?
import java.util.Collection;
import java.util.HashMap;
?
public class Map {
   public static void main(String[] args) {
       java.util.Map<Integer,String> map = new HashMap<>();
       map.put(1,"wowowo");
       map.put(2,"zhang");
       map.put(3,"zhangjunlong ");
       map.put(2,"woshizhang junlo");
       System.out.println(map.get(2));
       map.remove(2);
       System.out.println(map.size());
       System.out.println(map.get(2));//null
       map.clear();
       System.out.println(map.size());
       System.out.println(map.containsValue("zhangjunlong"));
       map.put(1,"zhangjunlong");
       System.out.println(map.containsValue("zhangjunlong"));
       map.put(3,"woshizhangjunlonh");
       map.put(4,"zhanfjunlonmg");
       Collection suoyoude =map.values();
       for (String s : map.values())
      {
           System.out.println(s);
?
      }
  }
}
?

map集合的遍历【非常重要】

第一种方式:获取所有的key,通过遍历所有key来遍历所有的value

遍历Map集合

获取所有的key,所有的key是一个Set集合

Set<Integer>keys = map.keySet();
遍历key。通过key获取value
 
   

迭代器遍历所有的value

 Set<Integer> keys = map.keySet();
       Iterator<Integer> it = keys.iterator();
?
       while ( it.hasNext()){
           Integer key = it.next();
           String value = map.get(key);
           System.out.println(
                   key + "="+ value
          );
?
      }

foreach 也可以

  for (Integer key : keys){
           System.out.println(key + "=" + map.get(key));
      }
?

第二种方式:Set<Map.Entry<K,V>> entrySet()

以上的方法是把Map集合直接全部转换成Set集合

Set集合中元素的类型是:Map.Entry

 

技术分享图片

foreach

 for (java.util.Map.Entry<Integer, String> node:set)
  {
       System.out.println(node.getKey() + "--->"+node.getValue());
  }
?
}

这种方式效率比较高,因为获取key和value都是直接从node对象对获取的属性值。

这种方式比较适合于大数据量

 

HashMap

哈希表或者散列表的数据结构

门帘子

HashMap集合

  • HashMap集合底层是哈希表|散列表的数据结构

  • 哈希表是一个怎么样的数据结构

    • 哈希表是一个数组和单向链表的结合体

    • 数组:在查询方面效率很高,随机增删方面效率较低

    • 单向链表:在随机增删方面效率较高,在查询方面效率较低

    • 哈希表将以上两种数据结构融合在一起,充分发挥了他们各自的优点

  • HashMap集合底层的源代码

    • 哈希值(哈希值是key的HashCode()方法的执行结果。hash值通过哈希函数|算法,可以转换存储成数组的下标)

技术分享图片

HashMap底层实际上就是一个数组

Node<K,V>[] table ;

哈希表、散列表:一维数组,这个赎罪中每一个元素是一个单向链表(数组和链表的结合体)

  • final int hash 哈希值:哈希值(哈希值是key的HashCode()方法的执行结果。hash值通过哈希函数|算法,可以转换存储成数组的下标)

  • final K key 存储到Map集合中的那个key

  • V value 存储到Map集合中的那个value

  • Node<K,V>next; 下一个节点的内存地址


最主要掌握 map.put(k,v) v=map.get(k)

map.put(k,v)

v=map.get(k)

以上两种方法的实现原理,是必须掌握的

map.put(k,v)实现原理

第一步:先将k,v封装到Node对象当中

第二步:底层先调用k的hashCode()方法得到hash值。然后通过哈希函数,哈希算法,将hash值转换成数组的下标,下标的位置如果没有任何元素,就把Node添加到这个位置上了,如果下标对应的位置上有链表,此时会拿着k和链表上每一个节点中的k进行equals,如果所有的equals方法返回值都是false,那么这个新节点将会被添加到链表的末尾,如果其中有一个equals返回了true,那么这个节点的value将会被覆盖

v=map.get(k)实现原理:

第一步:先调用k的hashCode()方法得到哈希值,通过哈希算法转成数组下标,通过数组下标快速定位到某个位置上,如果这个位置上什么也没有,返回null,如果这个位置上有单向链表,那么会拿着参数k和单向链表上的每一节点中的k进行equals,如果所有equals方法返回值是false,那么get方法返回null,只要其中有一个节点的k和参数k,equals的时候返回true,那么此时这个节点的value就是我们要找的value,get方法最终返回这个要找的value

技术分享图片

 

为什么哈希表的随机增删以及查询效率都很高

增删是在链表上完成,查询也不需要扫描全部,只需要部分扫描

重点: 通过讲解可以得出HashMap集合的key,会先后调用两个方法,一个方法是hashCode()一个方法是equals(),那么这两个方法都需要重写

为什么要重写equals方法!

因为equals方法默认比较的是两个对象的内存地址,我们应该比较的是内容

HashMap集合的key部分特点

无序,不可重复

为什么无序,因为不一定挂到哪个单向链表上

不可重复是怎么保证的

equals方法来保证HashMap集合的key不可重复、

如果key重复了,value会覆盖

放在HashMap集合key部分的元素其实就是放到HashSet集合中了

所以HashSet集合中的元素也需要同时重写hashCode()+equals()方法


注意:同一个单向链表的所有节点的Hash相同,因为他们的数组下标是一样的,但是同一个链表上k和k的equals方法肯定返回的都是false,都不相等

 

hashCode()方法重写的时候

HashMap使用不当是,无法发挥性能

假设将所有的hashCode()方法返回值固定为某个值,那么会导致底层哈希表变成纯单向链表,这种情况我们称为:散列分布不均匀

什么是散列分布均匀?

技术分享图片

重点:放在HashMap集合key部分的元素,以及放在HashSet集合中的元素,需要同时重写hashCode和equals方法

HashMap集合的默认初始化容量是16,默认加载因子是0.75

这个默认架子啊因子是当HashMap集合底层数组的容量达到75%的时候,数组开始扩容

技术分享图片

重点:记住。HashMap集合初始化容量必须是2的倍数,这也是官方推荐的,

这是因为达到散列均匀,为了提高HashMap集合的存取效率,所必须的。

 


向map集合中存,以及从Map集合中取,都是先调用key的hashCode方法,然后再调用equals方法!

equals方法有可能调用,也有可能不调用

  • 拿put(k,v)举例,什么时候equals不会调用?

    • k.hashCode()方法返回哈希值

    • 哈希值经过哈希算法转换成数组下标

    • 数组下标位置上如果是null,equals不需要执行

    •  

HashSet TreeSet Map

原文:https://www.cnblogs.com/geren/p/14827258.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!