集合之比较接口器+Map家族的HashMap+LinkedHashMap+Hashtable+ConcurrentHashMap

雨霖先森 2022-10-16 12:01:41

集合之比较接口器+Map家族的HashMap+LinkedHashMap+Hashtable+ConcurrentHashMap

一、比较器接口

1.内置比较器 -- Comparable

import java.util.TreeSet;
​
public class Test03 {
    public static void main(String[] args) {
        
        TreeSet<Student> set = new TreeSet<>();
        
        set.add(new Student("孙尚香", '女', 22, "2211", "001"));     
        set.add(new Student("安吉拉", '女', 25, "2211", "002"));     
        set.add(new Student("虞姬", '女', 19, "2211", "003"));     
        set.add(new Student("妲己", '女', 29, "2211", "004"));     
        set.add(new Student("杨贵妃", '女', 21, "2211", "005"));    
        set.add(new Student("钟无艳", '女', 20, "2211", "006"));    
        set.add(new Student("貂蝉", '女', 19, "2211", "007"));    
        set.add(new Student("大桥", '女', 18, "2211", "008"));    
        set.add(new Student("伽罗", '女', 21, "2211", "009"));    
        set.add(new Student("黄忠", '男', 25, "2211", "010"));     
        set.add(new Student("小乔", '女', 22, "2212", "001"));    
        set.add(new Student("阿珂", '女', 24, "2212", "002"));    
        set.add(new Student("瑶", '女', 20, "2212", "003"));   
        set.add(new Student("上官婉儿", '女', 22, "2212", "004"));  
        set.add(new Student("墨瞳茉拉", '女', 22, "2213", "004"));  
        
        for (Student stu : set) {
            System.out.println(stu);
        }
        
    } 
}
public class Student implements Comparable<Student> {
​
    private String name;
    private char sex;
    private int age;
    private String classId;
    private String id;
    
    public Student() {
        
    }
​
    
    public Student(String classId, String id) {
        this.classId = classId;
        this.id = id;
    }
​
​
    public Student(String name, char sex, int age, String classId, String id) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.classId = classId;
        this.id = id;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public char getSex() {
        return sex;
    }
​
    public void setSex(char sex) {
        this.sex = sex;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public String getClassId() {
        return classId;
    }
​
    public void setClassId(String classId) {
        this.classId = classId;
    }
​
    public String getId() {
        return id;
    }
​
    public void setId(String id) {
        this.id = id;
    }
    
    @Override
    public String toString() {
        return name + "\t" + sex + "\t" + age + "\t" + classId + "\t" + id;
    }
​
    //判断两个学生是否相同(班级号 + 学号)
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        
        if (obj instanceof Student) {
            Student stu = (Student) obj;
            if (classId.equals(stu.classId) && id.equals(stu.id)) {
                return true;
            }
        }
        return false;
    }
    //排序规则:按照年龄排序
    @Override
    public int compareTo(Student o) {
        //年龄差
        int num = this.age - o.age;
        if (num != 0) {
            return num;
        }
        
        if (this == o || this.equals(o)) {
            return 0;
        }
        //年龄相同,但是两个学生又不是同一个对象,我们还是返回1
        return 1;
    }
}

2.外置比较器 -- Comparator

1.应用场景:

需求:按照名字长度排序,长度一致按照年龄排序

2.比较器优先级别:外置比较器 > 内置比较器

import java.util.Comparator;
import java.util.TreeSet;
​
public class Test04 {
​
    public static void main(String[] args) {
        TreeSet<Student> set = new TreeSet<>(new Comparator<Student>(){
​
            @Override
            public int compare(Student o1, Student o2) {
            if (o1 == o2 || o1.equals(o2)) {
                return 0;
            }
            int len1 = o1.getName().length();
            int len2 = o2.getName().length();
            if (len1 != len2) {
                return len1 - len2;
            }
            int age1 = o1.getAge();
            int age2 = o2.getAge();
            if (age1 != age2) {
                return age1 - age2;
            }
                return 1;
            }
            
            });
        
        set.add(new Student("孙尚香", '女', 22, "2211", "001"));     
        set.add(new Student("安吉拉", '女', 25, "2211", "002"));     
        set.add(new Student("虞姬", '女', 19, "2211", "003"));     
        set.add(new Student("妲己", '女', 29, "2211", "004"));     
        set.add(new Student("杨贵妃", '女', 21, "2211", "005"));    
        set.add(new Student("钟无艳", '女', 20, "2211", "006"));    
        set.add(new Student("貂蝉", '女', 19, "2211", "007"));    
        set.add(new Student("大桥", '女', 18, "2211", "008"));    
        set.add(new Student("伽罗", '女', 21, "2211", "009"));    
        set.add(new Student("黄忠", '男', 25, "2211", "010"));     
        set.add(new Student("小乔", '女', 22, "2212", "001"));    
        set.add(new Student("阿珂", '女', 24, "2212", "002"));    
        set.add(new Student("瑶", '女', 20, "2212", "003"));   
        set.add(new Student("上官婉儿", '女', 22, "2212", "004"));  
        set.add(new Student("墨瞳茉拉", '女', 22, "2213", "004"));  
        
        for (Student stu : set) {
            System.out.println(stu);
        }
    }
}

3.扩展

1.内置比较器:对象要想存入TreeSet、TreeMap中,对象所属的类必须要实现内置比较器

2.外置比较器:当内置比较的规则不满足现在的需求,但又不能改动内置比较器规则时

二、Map家族的HashMap

1.HashMap的使用

2.特点:key是唯一的

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
import java.util.Map.Entry;
​
public class Test01 {
​
    public static void main(String[] args) {
        
        HashMap<String, Integer> map = new HashMap<>();
        
        //添加元素 -- 如果key是第一次添加,则返回null
        Integer  put1 = map.put("大桥",18);
        Integer  put2 = map.put("小乔",19);
        Integer  put3 = map.put("西施",25);
        Integer  put4 = map.put("王昭君",20);
        Integer  put5 = map.put("杨贵妃",23);
        Integer  put6 = map.put("貂蝉",28);
        
        System.out.println("put()的返回值:" + put1);
        System.out.println("put()的返回值:" + put2);
        System.out.println("put()的返回值:" + put3);
        System.out.println("put()的返回值:" + put4);
        System.out.println("put()的返回值:" + put5);
        System.out.println("put()的返回值:" + put6);
        
        //替换元素,返回被替换掉的值
        Integer put = map.put("大桥", 20);
        System.out.println("put()的返回值:" + put);
        
        //替换元素,返回被替换掉的值
        Integer replace = map.replace("大桥", 21);
        System.out.println("replace()的返回值" + replace);
        
        //替换元素,返回是否替换成功的boolean
        boolean bool = map.replace("西施", 25,23);
        System.out.println("替换元素,返回是否替换成功的boolean:" + bool);
        
        //清空所有元素
        //map.clear();
        
        System.out.println("判断map中是否有指定的key:" + map.containsKey("小乔"));//true
        System.out.println("判断map中是否有指定的value:" + map.containsValue(28));//true
        
        //获取指定key对应的value
        Integer integer = map.get("西施");
        System.out.println("获取指定Key对应 的value:" + integer);//23
​
        //获取指定key对应的value,如果没key,就返回默认值
        Integer orDefault = map.getOrDefault("貂蝉111", 666);
        System.out.println("获取指定key对应的value:" + orDefault);//666
​
        System.out.println("判断map集合中是否不包含元素:" + map.isEmpty());//false
​
        //将newMap中所有的元素都添加到map中
        HashMap<String, Integer> newMap = new HashMap<>();
        newMap.put("aaa", 10);
        newMap.put("bbb", 20);
        newMap.put("ccc", 30);
        map.putAll(newMap);
​
        //如果map中没有该key就添加,如果有就返回对应的value
        Integer putIfAbsent = map.putIfAbsent("ddd", 40);
        System.out.println("如果map中没有该key就添加,如果有就返回对应的value:" + putIfAbsent);
​
        //根据key删除映射关系
        map.remove("杨贵妃");
        //根据key+value删除映射关系
        map.remove("ccc", 30);
​
        System.out.println("获取map中映射关系的个数:" + map.size());//8
​
        //获取map中所有的value,返回集合
        Collection<Integer> values = map.values();
        System.out.println(Arrays.toString(values.toArray()));
​
        System.out.println("---------------");
​
        //遍历方式1 -- keySet()
        //思路:获取map中所有的key,将key存放在set集合中,遍历set集合将key取出,
        //就可以通过map获取key对应的value
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            Integer value = map.get(key);
            System.out.println(key + "---" + value);
        }
        
        System.out.println("---------------");
        
        //遍历方式2 -- entrySet()
        //entry:表示映射关系(key + value)
        //思路:获取map中所有的映射关系对象,将映射关系对象存放在set集合中,遍历set集合将映射关系对象取出,
        //就可以通过映射关系对象获取到key和value
        Set<Entry<String, Integer>> entrySet = map.entrySet();
        for (Entry<String, Integer> entry : entrySet) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " -- " + value);
        }
    }
}

三、LinkedHashMap

1.LinkedHashMap的使用

2.特点:key是唯一的

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.Map.Entry;
​
public class Test01 {
​
    public static void main(String[] args) {
        
        LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
        
        //添加元素 -- 如果key是第一次添加,则返回null
        Integer  put1 = map.put("大桥",18);
        Integer  put2 = map.put("小乔",19);
        Integer  put3 = map.put("西施",25);
        Integer  put4 = map.put("王昭君",20);
        Integer  put5 = map.put("杨贵妃",23);
        Integer  put6 = map.put("貂蝉",28);
        
        System.out.println("put()的返回值:" + put1);
        System.out.println("put()的返回值:" + put2);
        System.out.println("put()的返回值:" + put3);
        System.out.println("put()的返回值:" + put4);
        System.out.println("put()的返回值:" + put5);
        System.out.println("put()的返回值:" + put6);
        
        //替换元素,返回被替换掉的值
        Integer put = map.put("大桥", 20);
        System.out.println("put()的返回值:" + put);
        
        //替换元素,返回被替换掉的值
        Integer replace = map.replace("大桥", 21);
        System.out.println("replace()的返回值" + replace);
        
        //替换元素,返回是否替换成功的boolean
        boolean bool = map.replace("西施", 25,23);
        System.out.println("替换元素,返回是否替换成功的boolean:" + bool);
        
        //清空所有元素
        //map.clear();
        
        System.out.println("判断map中是否有指定的key:" + map.containsKey("小乔"));//true
        System.out.println("判断map中是否有指定的value:" + map.containsValue(28));//true
        
        //获取指定key对应的value
        Integer integer = map.get("西施");
        System.out.println("获取指定Key对应 的value:" + integer);//23
​
        //获取指定key对应的value,如果没key,就返回默认值
        Integer orDefault = map.getOrDefault("貂蝉111", 666);
        System.out.println("获取指定key对应的value:" + orDefault);//666
​
        System.out.println("判断map集合中是否不包含元素:" + map.isEmpty());//false
​
        //将newMap中所有的元素都添加到map中
        LinkedHashMap<String, Integer> newMap = new LinkedHashMap<>();
        newMap.put("aaa", 10);
        newMap.put("bbb", 20);
        newMap.put("ccc", 30);
        map.putAll(newMap);
​
        //如果map中没有该key就添加,如果有就返回对应的value
        Integer putIfAbsent = map.putIfAbsent("ddd", 40);
        System.out.println("如果map中没有该key就添加,如果有就返回对应的value:" + putIfAbsent);
​
        //根据key删除映射关系
        map.remove("杨贵妃");
        //根据key+value删除映射关系
        map.remove("ccc", 30);
​
        System.out.println("获取map中映射关系的个数:" + map.size());//8
​
        //获取map中所有的value,返回集合
        Collection<Integer> values = map.values();
        System.out.println(Arrays.toString(values.toArray()));
​
        System.out.println("---------------");
​
        //遍历方式1 -- keySet()
        //思路:获取map中所有的key,将key存放在set集合中,遍历set集合将key取出,
        //就可以通过map获取key对应的value
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            Integer value = map.get(key);
            System.out.println(key + "---" + value);
        }
        
        System.out.println("---------------");
        
        //遍历方式2 -- entrySet()
        //entry:表示映射关系(key + value)
        //思路:获取map中所有的映射关系对象,将映射关系对象存放在set集合中,遍历set集合将映射关系对象取出,
        //就可以通过映射关系对象获取到key和value
        Set<Entry<String, Integer>> entrySet = map.entrySet();
        for (Entry<String, Integer> entry : entrySet) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " -- " + value);
        }
    }
}

四、Hashtable

1.Hashtable的使用

2.key是唯一的

import java.util.Arrays;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Set;
import java.util.Map.Entry;
​
public class Test01 {
​
    public static void main(String[] args) {
        
        Hashtable<String, Integer> map = new Hashtable<>();
        
        //添加元素 -- 如果key是第一次添加,则返回null
        Integer  put1 = map.put("大桥",18);
        Integer  put2 = map.put("小乔",19);
        Integer  put3 = map.put("西施",25);
        Integer  put4 = map.put("王昭君",20);
        Integer  put5 = map.put("杨贵妃",23);
        Integer  put6 = map.put("貂蝉",28);
        
        System.out.println("put()的返回值:" + put1);
        System.out.println("put()的返回值:" + put2);
        System.out.println("put()的返回值:" + put3);
        System.out.println("put()的返回值:" + put4);
        System.out.println("put()的返回值:" + put5);
        System.out.println("put()的返回值:" + put6);
        
        //替换元素,返回被替换掉的值
        Integer put = map.put("大桥", 20);
        System.out.println("put()的返回值:" + put);
        
        //替换元素,返回被替换掉的值
        Integer replace = map.replace("大桥", 21);
        System.out.println("replace()的返回值" + replace);
        
        //替换元素,返回是否替换成功的boolean
        boolean bool = map.replace("西施", 25,23);
        System.out.println("替换元素,返回是否替换成功的boolean:" + bool);
        
        //清空所有元素
        //map.clear();
        
        System.out.println("判断map中是否有指定的key:" + map.containsKey("小乔"));//true
        System.out.println("判断map中是否有指定的value:" + map.containsValue(28));//true
        
        //获取指定key对应的value
        Integer integer = map.get("西施");
        System.out.println("获取指定Key对应 的value:" + integer);//23
​
        //获取指定key对应的value,如果没key,就返回默认值
        Integer orDefault = map.getOrDefault("貂蝉111", 666);
        System.out.println("获取指定key对应的value:" + orDefault);//666
​
        System.out.println("判断map集合中是否不包含元素:" + map.isEmpty());//false
​
        //将newMap中所有的元素都添加到map中
        Hashtable<String, Integer> newMap = new Hashtable<>();
        newMap.put("aaa", 10);
        newMap.put("bbb", 20);
        newMap.put("ccc", 30);
        map.putAll(newMap);
​
        //如果map中没有该key就添加,如果有就返回对应的value
        Integer putIfAbsent = map.putIfAbsent("ddd", 40);
        System.out.println("如果map中没有该key就添加,如果有就返回对应的value:" + putIfAbsent);
​
        //根据key删除映射关系
        map.remove("杨贵妃");
        //根据key+value删除映射关系
        map.remove("ccc", 30);
​
        System.out.println("获取map中映射关系的个数:" + map.size());//8
​
        //获取map中所有的value,返回集合
        Collection<Integer> values = map.values();
        System.out.println(Arrays.toString(values.toArray()));
​
        System.out.println("---------------");
​
        //遍历方式1 -- keySet()
        //思路:获取map中所有的key,将key存放在set集合中,遍历set集合将key取出,
        //就可以通过map获取key对应的value
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            Integer value = map.get(key);
            System.out.println(key + "---" + value);
        }
        
        System.out.println("---------------");
        
        //遍历方式2 -- entrySet()
        //entry:表示映射关系(key + value)
        //思路:获取map中所有的映射关系对象,将映射关系对象存放在set集合中,遍历set集合将映射关系对象取出,
        //就可以通过映射关系对象获取到key和value
        Set<Entry<String, Integer>> entrySet = map.entrySet();
        for (Entry<String, Integer> entry : entrySet) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " -- " + value);
        }
    }
}

五、ConcurrentHashMap

1.ConcurrentHashMap的使用

2.特点:key是唯一的

import java.util.Arrays;
import java.util.Collection;
​
import java.util.concurrent.ConcurrentHashMap;
import java.util.Set;
import java.util.Map.Entry;
​
public class Test01 {
​
    public static void main(String[] args) {
        
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
        
        //添加元素 -- 如果key是第一次添加,则返回null
        Integer  put1 = map.put("大桥",18);
        Integer  put2 = map.put("小乔",19);
        Integer  put3 = map.put("西施",25);
        Integer  put4 = map.put("王昭君",20);
        Integer  put5 = map.put("杨贵妃",23);
        Integer  put6 = map.put("貂蝉",28);
        
        System.out.println("put()的返回值:" + put1);
        System.out.println("put()的返回值:" + put2);
        System.out.println("put()的返回值:" + put3);
        System.out.println("put()的返回值:" + put4);
        System.out.println("put()的返回值:" + put5);
        System.out.println("put()的返回值:" + put6);
        
        //替换元素,返回被替换掉的值
        Integer put = map.put("大桥", 20);
        System.out.println("put()的返回值:" + put);
        
        //替换元素,返回被替换掉的值
        Integer replace = map.replace("大桥", 21);
        System.out.println("replace()的返回值" + replace);
        
        //替换元素,返回是否替换成功的boolean
        boolean bool = map.replace("西施", 25,23);
        System.out.println("替换元素,返回是否替换成功的boolean:" + bool);
        
        //清空所有元素
        //map.clear();
        
        System.out.println("判断map中是否有指定的key:" + map.containsKey("小乔"));//true
        System.out.println("判断map中是否有指定的value:" + map.containsValue(28));//true
        
        //获取指定key对应的value
        Integer integer = map.get("西施");
        System.out.println("获取指定Key对应 的value:" + integer);//23
​
        //获取指定key对应的value,如果没key,就返回默认值
        Integer orDefault = map.getOrDefault("貂蝉111", 666);
        System.out.println("获取指定key对应的value:" + orDefault);//666
​
        System.out.println("判断map集合中是否不包含元素:" + map.isEmpty());//false
​
        //将newMap中所有的元素都添加到map中
        ConcurrentHashMap<String, Integer> newMap = new ConcurrentHashMap<>();
        newMap.put("aaa", 10);
        newMap.put("bbb", 20);
        newMap.put("ccc", 30);
        map.putAll(newMap);
​
        //如果map中没有该key就添加,如果有就返回对应的value
        Integer putIfAbsent = map.putIfAbsent("ddd", 40);
        System.out.println("如果map中没有该key就添加,如果有就返回对应的value:" + putIfAbsent);
​
        //根据key删除映射关系
        map.remove("杨贵妃");
        //根据key+value删除映射关系
        map.remove("ccc", 30);
​
        System.out.println("获取map中映射关系的个数:" + map.size());//8
​
        //获取map中所有的value,返回集合
        Collection<Integer> values = map.values();
        System.out.println(Arrays.toString(values.toArray()));
​
        System.out.println("---------------");
​
        //遍历方式1 -- keySet()
        //思路:获取map中所有的key,将key存放在set集合中,遍历set集合将key取出,
        //就可以通过map获取key对应的value
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            Integer value = map.get(key);
            System.out.println(key + "---" + value);
        }
        
        System.out.println("---------------");
        
        //遍历方式2 -- entrySet()
        //entry:表示映射关系(key + value)
        //思路:获取map中所有的映射关系对象,将映射关系对象存放在set集合中,遍历set集合将映射关系对象取出,
        //就可以通过映射关系对象获取到key和value
        Set<Entry<String, Integer>> entrySet = map.entrySet();
        for (Entry<String, Integer> entry : entrySet) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " -- " + value);
        }
    }
}

3.HashMap vs LinkedHashMap vs Hashtable vs ConcurrentHashMap

1.共同点:使用都是一样的

2.特点:

HashMapkey唯一无序线程不安全
LinkedHashMapkey唯一有序线程不安全
ConcurrentHashMapkey唯一无序线程安全
Hashtablekey唯一无序线程安全

3.存储null键区别:

HashMap允许 
LinkedHashMap允许 
Hashtable不允许报错
ConcurrentHashMap不允许报错
import java.util.concurrent.ConcurrentHashMap;
​
public class Test02 {
​
    public static void main(String[] args) {
        
        ConcurrentHashMap<Object, Object> map = new ConcurrentHashMap<>();
        map.put(null, null);//报错
    }
}

4.Hashtable 和 ConcurrentHashMap的线程安全方式:

1.Hashtable加锁的方式:方法上加锁,效率低,弃用

2.ConcurrentHashMap加锁的方式:局部加锁+CAS,效率高

...全文
72 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

51,408

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧