集合之比较接口器+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;
}
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<>();
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 bool = map.replace("西施", 25,23);
System.out.println("替换元素,返回是否替换成功的boolean:" + bool);
System.out.println("判断map中是否有指定的key:" + map.containsKey("小乔"));
System.out.println("判断map中是否有指定的value:" + map.containsValue(28));
Integer integer = map.get("西施");
System.out.println("获取指定Key对应 的value:" + integer);
Integer orDefault = map.getOrDefault("貂蝉111", 666);
System.out.println("获取指定key对应的value:" + orDefault);
System.out.println("判断map集合中是否不包含元素:" + map.isEmpty());
HashMap<String, Integer> newMap = new HashMap<>();
newMap.put("aaa", 10);
newMap.put("bbb", 20);
newMap.put("ccc", 30);
map.putAll(newMap);
Integer putIfAbsent = map.putIfAbsent("ddd", 40);
System.out.println("如果map中没有该key就添加,如果有就返回对应的value:" + putIfAbsent);
map.remove("杨贵妃");
map.remove("ccc", 30);
System.out.println("获取map中映射关系的个数:" + map.size());
Collection<Integer> values = map.values();
System.out.println(Arrays.toString(values.toArray()));
System.out.println("---------------");
Set<String> keySet = map.keySet();
for (String key : keySet) {
Integer value = map.get(key);
System.out.println(key + "---" + value);
}
System.out.println("---------------");
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<>();
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 bool = map.replace("西施", 25,23);
System.out.println("替换元素,返回是否替换成功的boolean:" + bool);
System.out.println("判断map中是否有指定的key:" + map.containsKey("小乔"));
System.out.println("判断map中是否有指定的value:" + map.containsValue(28));
Integer integer = map.get("西施");
System.out.println("获取指定Key对应 的value:" + integer);
Integer orDefault = map.getOrDefault("貂蝉111", 666);
System.out.println("获取指定key对应的value:" + orDefault);
System.out.println("判断map集合中是否不包含元素:" + map.isEmpty());
LinkedHashMap<String, Integer> newMap = new LinkedHashMap<>();
newMap.put("aaa", 10);
newMap.put("bbb", 20);
newMap.put("ccc", 30);
map.putAll(newMap);
Integer putIfAbsent = map.putIfAbsent("ddd", 40);
System.out.println("如果map中没有该key就添加,如果有就返回对应的value:" + putIfAbsent);
map.remove("杨贵妃");
map.remove("ccc", 30);
System.out.println("获取map中映射关系的个数:" + map.size());
Collection<Integer> values = map.values();
System.out.println(Arrays.toString(values.toArray()));
System.out.println("---------------");
Set<String> keySet = map.keySet();
for (String key : keySet) {
Integer value = map.get(key);
System.out.println(key + "---" + value);
}
System.out.println("---------------");
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<>();
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 bool = map.replace("西施", 25,23);
System.out.println("替换元素,返回是否替换成功的boolean:" + bool);
System.out.println("判断map中是否有指定的key:" + map.containsKey("小乔"));
System.out.println("判断map中是否有指定的value:" + map.containsValue(28));
Integer integer = map.get("西施");
System.out.println("获取指定Key对应 的value:" + integer);
Integer orDefault = map.getOrDefault("貂蝉111", 666);
System.out.println("获取指定key对应的value:" + orDefault);
System.out.println("判断map集合中是否不包含元素:" + map.isEmpty());
Hashtable<String, Integer> newMap = new Hashtable<>();
newMap.put("aaa", 10);
newMap.put("bbb", 20);
newMap.put("ccc", 30);
map.putAll(newMap);
Integer putIfAbsent = map.putIfAbsent("ddd", 40);
System.out.println("如果map中没有该key就添加,如果有就返回对应的value:" + putIfAbsent);
map.remove("杨贵妃");
map.remove("ccc", 30);
System.out.println("获取map中映射关系的个数:" + map.size());
Collection<Integer> values = map.values();
System.out.println(Arrays.toString(values.toArray()));
System.out.println("---------------");
Set<String> keySet = map.keySet();
for (String key : keySet) {
Integer value = map.get(key);
System.out.println(key + "---" + value);
}
System.out.println("---------------");
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<>();
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 bool = map.replace("西施", 25,23);
System.out.println("替换元素,返回是否替换成功的boolean:" + bool);
System.out.println("判断map中是否有指定的key:" + map.containsKey("小乔"));
System.out.println("判断map中是否有指定的value:" + map.containsValue(28));
Integer integer = map.get("西施");
System.out.println("获取指定Key对应 的value:" + integer);
Integer orDefault = map.getOrDefault("貂蝉111", 666);
System.out.println("获取指定key对应的value:" + orDefault);
System.out.println("判断map集合中是否不包含元素:" + map.isEmpty());
ConcurrentHashMap<String, Integer> newMap = new ConcurrentHashMap<>();
newMap.put("aaa", 10);
newMap.put("bbb", 20);
newMap.put("ccc", 30);
map.putAll(newMap);
Integer putIfAbsent = map.putIfAbsent("ddd", 40);
System.out.println("如果map中没有该key就添加,如果有就返回对应的value:" + putIfAbsent);
map.remove("杨贵妃");
map.remove("ccc", 30);
System.out.println("获取map中映射关系的个数:" + map.size());
Collection<Integer> values = map.values();
System.out.println(Arrays.toString(values.toArray()));
System.out.println("---------------");
Set<String> keySet = map.keySet();
for (String key : keySet) {
Integer value = map.get(key);
System.out.println(key + "---" + value);
}
System.out.println("---------------");
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.特点:
HashMap | key唯一 | 无序 | 线程不安全 |
---|
LinkedHashMap | key唯一 | 有序 | 线程不安全 |
ConcurrentHashMap | key唯一 | 无序 | 线程安全 |
Hashtable | key唯一 | 无序 | 线程安全 |
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,效率高