java核心知识之集合详解五(Map集合和Collections工具类)

Map集合

Map 用于保存具有映射关系的数据,因此Map集合里保存着两组值 ,一组值用于保存 Map 里的 key ,另外一组值用于保存 Map 里的 value , key 和 value 都可以是任何引用类型的数据Map 的 key 不允许重复 ,即同一个 Map 对象的任何两个 key 通过 equals 方法比较总是返回 false 。

Map集合的示例图
在这里插入图片描述

Map集合子类或者实现类示例图
在这里插入图片描述

Map集合常用的API方法:

void clear(): 删除该 Map 对象中的所有 key - value 对 。

boolean containsKey(Object key): 查询 Map 中 是否包含指定的 key ,如果包含则返回 trueboolean containsValue(Object value):查询 Map 中 是否包含一个或多个 value ,如果包含则返回 true .

Set entrySet(): 返回 Map 中包含 的 key-value 对所组成的 Set 集合,每个集合元素都是 Map.Entry(EntryMap 的内部类)对象 。

Object get(Object key): 返 回 指定 key 所对应的 value; 如果此 Map 中不包含该 key ,则返回 nullboolean isEmpty():查询该 Map 是否为空(即不包含任何 key-value 对 ) ,如 果为空则返回 trueSet keySet(): 返回该 Map 中所有 key 组成的 Set 集合 。

Object put(Object key, Object value): 添加 一个 key-value 对,如果当前 Map 中己有一个与该 key相等的 key-value 对,则新的 key-value 对会覆盖原来的 key-value 对 。

void putAll(Map m): 将指定 Map 中的 key-value 对复制到本 Map 中 。

Object remove(Object key): 删除指定 key 所对应的 key-value 对,返回被删除 key 所关联的 value ,如果该 key 不存在,则返回 nullboolean remove(Object key, Object value): 这是 Java 8 新增的方法,删除指定 key 、 value 所对应的 key-value 对 。 如果从该 Map 中成功地删除该 key-value 对,该方法返回 true ,否则返回 falseint size(): 返回该 Map 里的 key-value 对的个数 。

Collection values(): 返回该 Map 里所有 value 组成的 Collection

示例代码:

import java.util.HashMap;
import java.util.Map;

/**
 * @author: 随风飘的云
 * @date 2022/03/20 23:06
 */
public class MapTest {
    public static void main(String[] args) {
        Map map = new HashMap();
        //成对放入多个 key-value 对
        map.put("你",100);
        map.put("我", 1000);
        map.put("他",10000);
        //多次放入的 key - value 对中 value 可以重复
        map.put("A", 100);
        //放入重复的 key 时 ,新的value会覆盖原有的 value
        //如果新的value覆盖了原有的 value ,该方法返回被覆盖的value
        System.out.println(map.put("你", -1));//输出100
        // 输出Map集合
        System.out.println(map);
        System.out.println(map.containsKey("我"));
        System.out.println(map.containsValue(100));
        for (Object key:map.keySet()) {
            System.out.println("Key: "+ key + " map: "+ map.get(key));
        }
        map.remove("A");
        System.out.println(map);
    }
}

结果:
在这里插入图片描述

Entry内部类:

Map 中包括一个内部类 Entry,该类封装了 一个 key-value 对。 Entry 包含如下三个方法 。

Object getKey(): 返回该 En町里包含的 key 值 。
Object getValue(): 返回该 Entry 里包含的value 值 。
Object setValue(V value): 设置该 Entry 里包含的 value 值,并返回新设置的 value 值 。

Map集合新增的API的方法

1、Object compute(Object key, BiFunction remappingFunction): 该方法使用remappingFunction 根据 原 key-value 对计算一个新 value 。 只要新 value 不为 null,就使用新value 覆盖原 value; 如果原 value 不为 null,但新 value 为 null ,则删除原 key-value对;如果原 value 、新 value 同时为 null , 那么该方法不改变任何 key-value 对,直接返回 null 。

2、Object computeIfAbsent(Object key, Function mappingFunction):如果传给该方法的 key 参数在 Map 中对应的 value 为 null ,则使用 mappingFunction 根据 key计算一个新的结果,如果计算结 果不为 null,则用计算结果覆盖原有的 value 。 如果原 Map 原来不包括该 key,那么该方法可能会添加一组 key-value 对 。

3、Object computeIfPresent(Object key, BiFunction remappingFunction):如果传给该方法的 key 参数 在 Map 中对应的 value 不为 null,该方法将使用 remappingFunction 根据原key、 value 计算一个 新的结果,如果计算结果不为 null,则使用该结果覆盖原来的 value; 如果计算结果为 null,则删除原 key-value 对 。

4、void forEach(BiConsumer action): 该方法是 Java 8 为 Map 新增的一个遍历 key-value 对的方法,通过该方法可以更简洁地遍历 Map 的 key-value 对 。

5、Object getOrDefault(Object key, V defaultValue): 获取指定 key 对应的 value 。 如果该 key 不存在,则返回 defaultValue。

6、Object merge(Object key, Object value, BiFunction remappingFunction): 该方法会先根据 key 参数获取该 Map 中对应的 value 。 如果获取的 value 为 null,则直接用传入的 value 覆盖原有的 value (在这种情况下,可能要添加一组 key-value 对 ) ;如果获取的value 不为 null ,则使用remappingFunction 函数根据原 value 、新 value 计算一个新的结果,并用得到的结果去覆盖原有 的 value 。

7、Object putlfAbsent(Object key, Object value): 该方法会自动检测指定 key 对应的value 是否为 null,如果该 key 对应的 value 为 null,该方法将会用新 value 代替原来的 null 值 。

8、Object replace(Object key, Object value): 将 Map 中指定 key 对应的 value替换成新 value 。与传统put()方法不同的是,该方法不可能添加新的 key-value 对 。 如果尝试替换的 key 在原 Map 中不存在,该方法不会添加 key-value 对,而是返回 null 。

9、boolean replace(K key, V oldValue, V newValue): 将 Map 中指定 key-value对的原 value 替换成新value 。如果在 Map 中找到指定的 key-value 对,则执行替换并返回 true ,否则返回false 。

10、replaceAll(BiFunction function): 该方法使用 BiFunction 对原 key-value 对执行计算,并将计算结果作为该 key-value 对的 value 值 。

Map总体方法
在这里插入图片描述

HashMap和HashTable的区别

1、线程安全不同: HashTable是一个线程安全的Map实现类,但是HashMap是线程不安全的实现类。因为线程安全问题,HashMap比HashTable性能高。
2、内部方法不同: HashTable内部的方法基本都经过synchronized 修饰。
例如:
在这里插入图片描述 3、存储值不同: HashTable实现类不可以使用null的key值或者是value值,如果在程序中添加null值,将会引发空指针异常(NUllPointerException)。但是HashMap可以使用null值作为key值或者是value值。
4、初始容量不同和每次扩容大小容量不同。 如果创建时不指定容量的大小,那么HashTable默认初始容量大小为11,每次扩充变为原来的2n+1倍。HashMap实现类初始化容量大小为16,每一次扩容变为原来的两倍。 如果创建时指定了容量大小,HashTable实现类直接使用指定的容量大小,而HashMap会扩充为原来的2的幂次方大小。
6、底层数据结构不同: HashMap实现类,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。

LinkedHashMap 实现类

基本原理

LinkedHashMap 使用双向链表来维护 key-value 对的次序(其实只需要考虑 key 的次序) ,该链表负责维护 Map 的迭代顺序,迭代顺序与 key-value 对的插入顺序保持一致。
LinkedHashMap 可以避免对 HashMap 、 Hashtable 里 的 key-value 对进行排序(只要插入 key-value对时保持顺序即可),同时又可避免使用 TreeMap 所增加的成本 。LinkedHashMap 需要维护元素的插入顺序,因此性能略低于 HashMap 的性能;但因为它以链表来维护内部顺序,所以在迭代访问 Map 里的全部元素时将有较好的性能 。

实例代码:

import java.util.LinkedHashMap;

/**
 * @author: 随风飘的云
 * @describe:
 * @date 2022/03/22 22:28
 */
public class LinkedHashMapTest {
    public static void main(String[] args) {
        LinkedHashMap scores = new LinkedHashMap();
        scores.put("语文" , 80);
        scores.put("英文" , 82);
        scores.put("数学" , 76);
        // 调用forEach方法遍历scores里的所有key-value对
        scores.forEach((key, value) -> System.out.println(key + "-->" + value));
    }
}

结果:
在这里插入图片描述

SortedMap 接口和 TreeMap 实现类

基本原理

SortMap接口有一个TreeMap实现类,TreeMap 就是 一个红黑树数据结构 , 每个 key-value 对即作为红黑树的一个节点 。 TreeMap 存储key-value 对(节点)时, 需要根据 key 对节点进行排序。 TreeMap 可以保证所有的 key-value 对处于有序状态。 TreeMap 也有两种排序方式。

1、自然排序: TreeMap实现类的所有Key必须要实现Comparable接口,而且所有的key必须要是同一个类对象的,否则会抛出ClassCastException.
2、定制排序: 创建 TreeMap 时,传入一个 Comparator 对象, 该对象负责对 TreeMap 中的所有key 进行排序 。采用定制排序时不要求 Map的 key 实现 Comparable 接口。

TreeMap中判断两个key相等的方法是两个key通过compareTo()方法返回0, 如果使用自定义类作为TreeMap实现类的key时,应当重写equals()方法和compareTo()方法,使得两个方法的返回结果一致。

TreeMap实现类提供一系列的访问Key-Value方法如下:

Map.Entry fIrstEntry(): 返回该 Map 中 最小 key 所对应的 key-value 对,如果该 Map 为 空, 则返回 nullObject fIrstKey(): 返回该 Map 中的最小 key 值 , 如果该 Map 为 空, 则返回 nullMap.Entry lastEntry(): 返回该 Map 中 最大 key 所对应的 key-value 对,如果该 Map 为空或不存在这样的key-value对,则都返回 nullObject lastKey(): 返回该 Map中的最大 key 值,如果该 Map为空或不存在这样的 key. 则都返回 nullMap.Entry higherEntry(Object key): 返回 该 Map 中位于 key 后 一位 的 key-value 对 ( 即大于指定key 的最小 key 所对应的 key-value 对 )。如果该 Map 为空 ,则 返回 nullMap.Entry lowerEntry(Object key): 返回该 Map 中 位于 key 前一位的 key-value 对(即 小于指定key 的最大 key 所对应的 key-value 对) 。 如果该 Map 为 空或不存在这样 的 key-value 对,则都返回 null 

Object lowerKey(Object key): 返回该 Map 中位于 key 前一位的 key 值(即小于指定 key 的最大key 值) 。 如果 该 Map 为 空或不存在这样的 key. 则都返回 nullNavigableMap subMap(Object fromKey, boolean fromInclusive, Object toKey, boolean toInclusive):
返回该 Map 的子 Map. 其 key 的范围是从 fromKey (是否包括取决于第二个参数) 到 toKey (是否包括取决于第四个参数)SortedMap subMap(Object 仕omKey, Object toKey): 返回该 Map 的子 Map. 其 key 的 范围是从
fromKey (包括 〉 到 toKey (不包括)SortedMap tailMap(Object 企omKey): 返回该 Map 的子 Map. 其 key 的 范围是大于 fromKey (包括)的所有 key 。

NavigableMap tailMap(Object fromKey, boolean inclusive): 返回该 Map 的子 Map. 其 key 的范围是大于 fromKey  (是否包括取决于第二个参数〉的所有 key 。

SortedMap headMap(Object toKey): 返回该 Map 的子 Map. 其 key 的范围是小于 toKey (不包括)的所有 key 。

NavigableMap headMap(Object toKey, boolean inclusive): 返回 该 Map 的子 Map. 其 key 的范围
是小于 toKey (是否包括取决于第二个参数) 的所有 key 。

实例代码:

import java.util.TreeMap;

/**
 * @author: 随风飘的云
 * @describe:
 * @date 2022/03/22 22:47
 */
class R implements Comparable
{
    int count;
    public R(int count)
    {
        this.count = count;
    }
    public String toString()
    {
        return "R[count:" + count + "]";
    }
    // 根据count来判断两个对象是否相等。
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj != null	&& obj.getClass() == R.class)
        {
            R r = (R)obj;
            return r.count == this.count;
        }
        return false;
    }
    // 根据count属性值来判断两个对象的大小。
    public int compareTo(Object obj)
    {
        R r = (R)obj;
        return count > r.count ? 1 :
                count < r.count ? -1 : 0;
    }
}
public class TreeMapTest {
    public static void main(String[] args) {
        TreeMap tm = new TreeMap();
        tm.put(new R(3) , "123456");
        tm.put(new R(-5) , "abcde");
        tm.put(new R(9) , "a1b2c3d4e5");
        System.out.println(tm);
        // 返回该TreeMap的第一个Entry对象
        System.out.println(tm.firstEntry());
        // 返回该TreeMap的最后一个key值
        System.out.println(tm.lastKey());
        // 返回该TreeMap的比new R(2)大的最小key值。
        System.out.println(tm.higherKey(new R(2)));
        // 返回该TreeMap的比new R(2)小的最大的key-value对。
        System.out.println(tm.lowerEntry(new R(2)));
        // 返回该TreeMap的子TreeMap
        System.out.println(tm.subMap(new R(-1) , new R(4)));
    }
}

结果:
在这里插入图片描述

WeakHashMap 实现类

基本原理

WeakHashMap 与 HashMap 的用法基本相似 。 与 HashMap 的 区别在于,HashMap 的 key 保留了对实际对象的强引用,这意味着只要该 HashMap 对象不被销毁,该 HashMap 的所有 key 所引用的对象就不会被垃圾回收,HashMap 也不会自动删除这些 key 所对应的 key-value 对 ;但 WeakHashMap 的 key只保留了对实际对象的弱引用,这意味着如果 WeakHashMap 对象的 key 所引用的对象没有被其他强引用变量所引用,则这些 key 所引用的对象可能被垃圾回收, WeakHashMap 也可能自动删除这些 key 所对应的 key-value 对 。

实例源码:

import java.util.WeakHashMap;

/**
 * @author: 随风飘的云
 * @describe:
 * @date 2022/03/22 23:05
 */
public class WeakHashMapTest {
    public static void main(String[] args) {
        WeakHashMap<String, Object> map = new WeakHashMap<>();
        map.put(new String("A"), new String("1"));
        map.put(new String("B"), new String("12"));
        map.put(new String("C"), new String("13"));

        System.out.println(map);

        map.put("D", new String("45"));
        System.gc();

        System.out.println(map);

    }
}

结果:
在这里插入图片描述

IdentityHashMap 实现类

基本原理

IdentityHashMap 实现类的实现机制与 HashMap 基本相似,但它在处理两个 key 相等时比较独特:在IdentityHashMap 中,当且仅当 两个 key 严格相等 (key1 == key2) 时, IdentityHashMap 才认为两个 key相等;对于普通的 HashMap 而言,只要 key1 和 key2 通过 equals()方法比较返回 true ,且它们的 hashCode值相等即可 。

实例源码:

import java.util.IdentityHashMap;

/**
 * @author: 随风飘的云
 * @describe:
 * @date 2022/03/22 23:11
 */
public class IdentityHashMapTest {
    public static void main(String[] args) {
        IdentityHashMap map = new IdentityHashMap();
        // 通过比较 == 不等,
        map.put(new String("java语言"),100);
        map.put(new String("java语言"), 120);
		// 常量,只能添加一个。
        map.put("a", 100);
        map.put("a", 110);
        System.out.println(map);
    }
}

结果:
在这里插入图片描述

EnumMap 实现类

基本原理

EnumMap 是一个与枚举类一起使用的 Map实现, EnumMap 中的所有 key 都必须是单个枚举类的枚举值 。 创建 EnumMap 时必须显式或隐式指定它对应的枚举类。 EnumMap 具有如下特征 。

1、EnumMap在内部以数组形式保存,所以这种实现形式非常紧凑、高效 。
2、EnumMap 根据 key 的自然顺序(即枚举值在枚举类中的 定义顺序〉来维护 key-value 对的顺序 ,当程序通过 keySet()、 entrySet() 、 values()等方法遍历EnumMap 时可以看到这种顺序 。
3、EnumMap 不允许使用 null 作为 key ,但允许使用 null 作为 value 。如果试图使用 null 作为 key时将抛出 NullPointerException 异常 。 如果只是查询是否包含值为 null 的key,或只是删除值为null 的key ,都不会抛出异常 。

与创建普通的 Map 有所区别的是,创建 EnumMap 时必须指定一个枚举类,从而将该 EnurnMap 和
指定枚举类关联起来 。

实例源码:

import java.util.EnumMap;

/**
 * @author: 随风飘的云
 * @describe:
 * @date 2022/03/22 23:19
 */
enum Season {
    SPRING,SUMMER,FALL,WINTER
}
public class EnumMapTest {
    public static void main(String[] args) {
        // 创建EnumMap对象,该EnumMap的所有key都是Season枚举类的枚举值
        EnumMap enumMap = new EnumMap(Season.class);
        enumMap.put(Season.SUMMER , "夏日炎炎");
        enumMap.put(Season.SPRING , "春暖花开");
        System.out.println(enumMap);
    }
}

结果:
在这里插入图片描述

各种Map集合类的性能分析

对于 Map 的常用实现类而言,虽然 HashMap 和 Hashtable 的实现机制几乎一样,但由于 Hashtable
是一个古老的、线程安全的集合,因此 HashMap 通常比 Hashtable 要快 。

TreeMap 通常比 HashMap 、 Hashtable 要慢( 尤其在插入、删除 key-value 对时更慢),TreeMap
底层采用红黑树来管理 key-value 对(红黑树的每个节点就是一个 key-value 对) 。

使用 TreeMap 有一个好处::TreeMap 中的 key-value 对总是处于有序状态 ,无须专 门进行排序操作 。当 TreeMap 被填充之后,就可以调用 keySet(),取得由 key 组成的 Set,然后使用 toArray()方法生成 key的数组,接下来使用Arrays 的 binarySearch()方法在己排序的数组中快速地查询对象。

对于 一般的应用场景 , 程序应该多考虑使用 HashMap ,因为 HashMap 正是为快速查询设计的(HashMap 底层其实也是采用数组来存储 key-value 对 〉 。 但如果程序需要一个总是排好序的 Map 时,则可以考虑使用 TreeMap 。

LinkedHashMap 比 HashMap 慢一 点,因为它需要维护链表来保持 Map 中 key-value 时的添加顺序。IdentityHashMap 性能没有特别出色之处 ,因为它采用与 HashMap 基本相似的实现 , 只是它使用 == 而不是 equals()方法来判断元素相等 。 EnumMap 的性能最好 ,但它只能使用同一个枚举类的枚举值作为 key 。

Collections工具类

排序

Collections 提供了如下常用的类方法用于对 List 集合元素进行排序 。

void reverse(List list): 反转指定 List 集合中元素的顺序 。

void shuffie(List list):List 集合元素进行随机排序 (shuffie 方法模拟了"洗牌"动作)void sort(List list): 根据元素的自然顺序对指定 List 集合的元素按升序进行排序。

void sort(List list, Comparator c): 根据指定 Comparator 产生的顺序对 List 集合元素进行排序 。

void swap(List list, int i, int j): 将指定 List 集合中的 i 处元素和 j 处元素进行交换。

void rotate(List list , int distance): 当 distance 为正数时,将 list 集合的后 distance 个元素"整体"移到前面:当 distance 为负数时,将 !ist 集合的前 distance 个元素"整体"移到后面 。 该方法不会改变集合的长度 。

替换

Collection s 还提供了如下常用的用于查找 、 替换集合元素的类万法 。

int binarySearch(List list, Object key): 使用 二分搜索法搜索指定的 List 集合,以获得指定对象在 List
集合中的索引。如果要使该方法可 以正常工作,则必须保证 List 中的元素己经处于有序状态。

Object max(Collection coll): 根据元素的自然顺序,返 回给定集合中的最大元素。

Object max(Collection coll, Comparator comp): 根据 Comparator 指定的顺序 ,返回给定集合中的最大元素 。

Object min(Collection coll) : 根据元素的自然顺序,返回给定集合中的最小元素 。

Object min(Collection  coll, Comparator comp): 根据 Comparator 指 定的顺序,返回给定集合中的
最小元素 。

void fill(List list, Object obj): 使用指定元素 obj 替换指定 List 集合中的所有元素 。

int frequency(Collection c, Object o): 返回指定集合中指定元素的出现次数 。

int indexOfSubList(List source, List target) : 返回子 List 对象在父 List 对象中第一次出现的位置索引:如果父 List 中没有出现这样的子 List,则返回-1int lastIndexOfSubList(List source, List target): 返回子 List 对象在父 Li st 对象中最后一 次出现 的
位置索引 ;如果父 List 中没有出现这样的子 List,则返回-1boolean replaceAll(List list, Object o ldVal, Object newVal) : 使用 一个新值 newVal 替换 List 对象的所有旧值oldVal 。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值