[java]Map和Set

Map和Set是两个集合类的接口。

map的核心模型是Key-Value模型,set的模型是Key模型

Map和Set都有两种实现,分别是红黑树实现和hash实现

一、TreeMap

TreeMap和TreeSet都是红黑树,红黑树是一种搜索树,TreeMap和TreeSet都将key作为红黑树排序的依据,在查找数据时,也是使用红黑树查找key值,所以TreeMap和TreeSet的key类型需要实现了comparable接口作为红黑树排序的基础。

TreeMap的常用方法:

(一)创建一个TreeMap

TreeMap是一个泛型类,有key和value两个类型参数,key值是决定用来比较确定位置的值,value值是与key值绑定的实值。

TreeMap<K,V> map =new TreeMap<>();

创建一个TreeMap对象。

(二)向TreeMap中插入数据

V put(K k,V v);

向map中插入一个key-value键值对,并返回value的值,如果map之前存在相同的key值,则将之前的kay值对应的value值覆盖。

(三)向TreeMap中删除一个数据

V remove(K key);

删除map中和key值相同的k-v键值对,并返回对应的value值,如果map中不存在这个key值,则返回null值。

(四)用key查询map中对应的value值

V get(K key);

如果map中不存在这个key值则返回null

V getOrDefault(K key,V default);

查询对应key值的value值,如果key值不存在,则返回默认值。

(五)将map中所有的key值组织起来,放入一个set里面

Set<Key> keySet();

(六)将map中对应的value值组织起来,放入一个实现了colleciton接口的集合类里面

Collection<Value> values();

(七)查询map中是否包含某个key值或者value值

bool containsKey(Object key);

bool containsValue(Object value);

(八)Entry类

Entry是TreeMap的内部类。Entry就是TreeMap中用来存储键值对的节点类。Entry内部有包含左右子树节点。Entry是可比较的。

Entry的三个常用方法

(1)获取entry的key值

K getKey();

(2)获取Entry的value值

V getValue();

(3)设置Entry的value值

V setValue(V value);

(九)获取所有的键值对Entry节点,并以set的方式组织起来。

Set<Map.Entry<K,V>> entrySet();

EntrySet这个方法获取了所有的键值对,这个方法是为了遍历Map中的节点实现的。

正常情况下,单独的Map对象无法遍历其中的节点,因为map没有下标,并且没有实现迭代器接口,无法使用迭代器,也无法使用forEach。

为了遍历Map中的节点所以有了EntrySet,KeySet,Values。

set实现了迭代器接口,可以使用迭代器,也可以使用forEach,Values的返回值是实现了Collection接口的,也能遍历。

二、TreeSet

TreeSet的底层是TreeMap,TreeSet将TreeMap的Value值以一个默认的object对象自动填充,使用时只需要传入Key值。所以TreeSet的底层还是红黑树。

三、HashMap

hashMap中的键值对是没有顺序的,因为HashMap是使用哈希函数的方法将关键码转化为存储地址,只要知道关键码和哈希方法,就可以通过计算得出存储地址,所以HashMap中的键值对并没有顺序。被HashMap传入的key类型必须要有正确的hashCode和equals方法。

hashCode和equals必须要使用相同的标准判断,当两个对象hashCode相同时,需要使用equals判断这两个对象是相同的还是只有hashCode相同,但是实际上是两个对象。

默认的equals只是比较两个对象的内存地址是否相等,所以要想用对象的内容来判断两个对象是否相等需要重写equals方法。

要想以内容来确定hashcode,也要重写hashcode方法。

(一)哈希冲突:不同的关键码经过哈希函数计算得出相同的存储地址。

冲突是肯定会发生的,我们能做的就只是降低冲突发生的概率。

(二)降低冲突发生的概率的方法

(1)设计合理的哈希函数

哈希函数的设计原则:

哈希函数比较简单;

哈希函数的定义域应该包括所有的关键码,若表的的长度为m,则哈希函数的值域应该在0-m-1之间;

哈希函数计算出来的地址应该均匀;

(2)减小负载因子

负载因子=放入hash表中的元素个数/hash表的长度

负载因子越大,冲突的概率越大。

HashMap的默认负载因子为0.75,只要负载因子超过0.75,HashMap就会自动扩容。

(三)解决hash冲突

hash冲突是必定发生的,当冲突发生时,需要对冲突进行处理。

冲突处理有两种方法:开散列和闭散列。

(1)闭散列

闭散列:也叫开方地址法,当发生哈希冲突时,如果hash表并未被装满,则将要放入的值放在最近的空位置上。

放在空位置有两种方法。线性探测法和二次探测法

线性探测法:当发生冲突时,依次向后探测,知道找到空位置。

二次探测法:发生冲突时,用函数

H是函数计算出来的存储位置,i是第几次计算,m是表的长度

使用闭散列的方法处理hash冲突时,不能随便的删除表中的元素,否则查找一个使用了探测法来计算存储位置的数据时,可能回查找不到,所以闭散列的删除不是直接删除,删除也只能使用其他标记位来逻辑删除。

(2)开散列(哈希桶)

开散列解决冲突的方式是,将插入的数据包装为链表的节点,如果发生冲突,在冲突的存储位置上已经存在的节点上头插或者尾插。(JDK1.7之前用的是头插,JDK1.8用的是尾插)

并且当数组的长度超过64,链表的长度超过8,链表将会变成红黑树。

开散列的解决方案虽然冲突时会让链表越来越长,但是链表长度超过8时链表会转变为红黑树,查找链表的效率会提高,并且存在着负载因子,随着表中给的数据增多,负载因子变大,当负载因子到达临界条件时,hash表会扩容,扩容过后数据的存储位置都会重新计算,链表的长度也会变短,所以可以认为链表的长度是常数,hash表的查询时间复杂度是O(1);

HashMap的实现就是使用的开散列的方法

四、HashSet

HashSet也是以HashMap为底层的将value值用默认对象实例化。使用方法和TreeSet相差不大。

总结:

map可以分离所有的value和key值存储带set当中。

map的key值是唯一的,不能改变,如果要改变,只能先修改,再插入。

set实现了Collection接口。

set的key值是唯一的,set不能存储重复的数据,set最大的作用就是去重,set的key不仅是关键码,也是set存储的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java,也有类似于C++ STLmapset的容器。Javamapset都是基于接口实现,常用的实现类有HashMap、TreeMap、LinkedHashMap等。常用的set实现类有HashSet、TreeSet、LinkedHashSet等。 Map接口和Set接口的主要区别在于,Map接口用于存储键值对,而Set接口用于存储不重复的元素。Map接口提供了put()、get()、remove()等方法,Set接口提供了add()、remove()、contains()等方法。 HashMap是一种基于哈希表实现的Map接口的实现类,它提供了快速的查找、插入和删除操作,查找、插入和删除操作的时间复杂度都为O(1)。HashMap的键和值都可以为null,但HashMap不保证元素的有序性。如果需要按照元素的插入顺序访问元素,可以使用LinkedHashMap。 TreeMap是一种基于红黑树实现的Map接口的实现类,它保证了元素的有序性,元素按照键的自然顺序或比较器顺序进行排序。TreeMap的查找、插入和删除操作的时间复杂度都为O(logN)。 HashSet是一种基于哈希表实现的Set接口的实现类,它提供了快速的查找、插入和删除操作,查找、插入和删除操作的时间复杂度都为O(1)。HashSet不保证元素的有序性,元素可以为null。 TreeSet是一种基于红黑树实现的Set接口的实现类,它保证了元素的有序性,元素按照自然顺序或比较器顺序进行排序。TreeSet的查找、插入和删除操作的时间复杂度都为O(logN)。 LinkedHashSet是一种基于哈希表和链表实现的Set接口的实现类,它保证了元素的插入顺序,同时提供了快速的查找、插入和删除操作。LinkedHashSet的查找、插入和删除操作的时间复杂度都为O(1)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值