一、双列集合概念
特点:
①双列集合一次需要存储一对数据,分别为键和值
②键不能重复,值可以重复
③键和值是一一对应的,每一个键只能找到自己对应的值
④键+值这个整体,称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”
二、Map集合
(一)Map集合方法:
Map集合是双列集合的顶层接口,它的功能是全部双列集合都可以继承使用的
示例代码:
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
//Map集合是一个接口,因此使用多态的形式创建其对象
Map<String,String> map=new HashMap<>();
//添加元素put方法
// 功能:添加/覆盖
//添加数据时,如果键不存在,那么直接把键值对对象 添加到map集合中
//如果键存在,则会把原有的键值对对象覆盖,并且返回被覆盖的值
map.put("郭靖","黄蓉");
map.put("韦小宝","木健平");
map.put("尹志平","小龙女");
System.out.println(map); //{韦小宝=木健平, 尹志平=小龙女, 郭靖=黄蓉}
System.out.println(map.put("韦小宝","双儿")); //木健平
System.out.println(map); //{韦小宝=双儿, 尹志平=小龙女, 郭靖=黄蓉}
//删除 删除键值对对象,返回对应的值
System.out.println(map.remove("郭靖")); //黄蓉
System.out.println(map); //{韦小宝=双儿, 尹志平=小龙女}
//清空
//map.clear();
//System.out.println(map); //{}
//判断是否包含
boolean keyresult=map.containsKey("韦小宝");
boolean keyresult2=map.containsKey("宝");
System.out.println(keyresult); //true
System.out.println(keyresult2); //false
//判断是否为空
boolean result=map.isEmpty();
System.out.println(result); //false
//长度
int size=map.size();
System.out.println(size); //2
}
}
(二)Map集合第一种遍历方式(键找值):
import java.util.*;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
//Map集合是一个接口,因此使用多态的形式创建其对象
Map<String,String> map=new HashMap<>();
map.put("郭靖","黄蓉");
map.put("韦小宝","木健平");
map.put("尹志平","小龙女");
//遍历(键找值):
//获取所有键值,将这些键值放到一个单列集合当中
//增强for遍历:
Set<String> keys=map.keySet();
for(String key:keys){
String value=map.get(key);
System.out.println(key+"="+value);
//韦小宝=木健平
//尹志平=小龙女
//郭靖=黄蓉
}
//迭代器遍历
Iterator<String> it= keys.iterator();
while(it.hasNext()){
String str=it.next();
String value=map.get(str);
System.out.println(str+"="+value);
//韦小宝=木健平
//尹志平=小龙女
//郭靖=黄蓉
}
//匿名内部类 + lambda简化 迭代
keys.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
String value=map.get(s);
System.out.println(s+"="+value);
}
});
//韦小宝=木健平
//尹志平=小龙女
//郭靖=黄蓉
keys.forEach(s->{
String value=map.get(s);
System.out.println(s+"="+value);
}
);
//韦小宝=木健平
//尹志平=小龙女
//郭靖=黄蓉
}
}
(三)Map集合第二种遍历方式(键值对)
import java.util.*;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
//Map集合是一个接口,因此使用多态的形式创建其对象
Map<String, String> map = new HashMap<>();
map.put("放逐之刃", "瑞文");
map.put("邪恶小法师", "小法");
map.put("奥特曼", "迪迦");
//Map集合的第二种遍历(键值对对象)
//通过 一个方法获取所有的键值对对象,返回一个set集合
Set<Map.Entry<String, String>> entries = map.entrySet();
//遍历entries这个集合,得到里面每一个键值对对象
//增强for遍历:
for(Map.Entry<String,String> entry:entries){
String key=entry.getKey();
String value=entry.getValue();
System.out.println(key+"="+value);
//邪恶小法师=小法
//奥特曼=迪迦
//放逐之刃=瑞文
}
//Set集合中装着三个键值对对象
System.out.println(entries);//[邪恶小法师=小法, 奥特曼=迪迦, 放逐之刃=瑞文]
//迭代器形式遍历
Iterator<Map.Entry<String,String>> iterator=entries.iterator();
while(iterator.hasNext()){
Map.Entry<String ,String> m=iterator.next();
String str1=m.getKey();
String str2=m.getValue();
System.out.println(str1+"="+str2);
//邪恶小法师=小法
//奥特曼=迪迦
//放逐之刃=瑞文
}
//匿名内部类+lambda表达式简化 遍历
entries.forEach(new Consumer<Map.Entry<String, String>>() {
@Override
public void accept(Map.Entry<String, String> s) {
String s1=s.getKey();
String s2=s.getValue();
System.out.println(s1+"="+s2);
//邪恶小法师=小法
//奥特曼=迪迦
//放逐之刃=瑞文
}
});
//lambda表达式简化
entries.forEach(s->{
String s1=s.getKey();
String s2=s.getValue();
System.out.println(s1+"="+s2);
//邪恶小法师=小法
//奥特曼=迪迦
//放逐之刃=瑞文
});
}
}
(四)Map集合第三种遍历方式(Lambda表达式)
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
//Map集合是一个接口,因此使用多态的形式创建其对象
Map<String, String> map = new HashMap<>();
map.put("德玛西亚之力", "盖伦");
map.put("诺克萨斯之手", "德莱厄斯");
map.put("飞机", "库奇");
//匿名内部类
map.forEach(new BiConsumer<String, String>() {
@Override
public void accept(String s, String s2) {
System.out.println(s+"="+s2);
}
//德玛西亚之力=盖伦
//诺克萨斯之手=德莱厄斯
//飞机=库奇
});
//Lambda表达式遍历
map.forEach((s,s2)-> System.out.println(s+"="+s2));
//德玛西亚之力=盖伦
//诺克萨斯之手=德莱厄斯
//飞机=库奇
}
}
三、HashMap集合
(一)HashMap集合特点:
①HashMap是Map接口的一个实现类
②没有额外需要学习的特有方法,直接使用Map里面的方法就可以
③特点都是由键决定的:无序、不重复、无索引
④HashMap跟HashSet底层逻辑一样,都是哈希表结构
(二)底层原理:
四、LinkedHashMap集合
由键决定:有序、不重复、无索引
有序:保证元素存储和取出的顺序一致
原理:底层数据结构依然是哈希表,只是每个键值对元素又额外的多了一个双链表机制来记录存储的顺序。
示例代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
LinkedHashMap<String,Integer> lhm=new LinkedHashMap<>();
lhm.put("A",1);
lhm.put("A",0);
lhm.put("B",2);
lhm.put("C",3);
System.out.println(lhm); //{A=0, B=2, C=3}
}
}
五、TreeMap集合
TreeMap与 TreeSet底层原理一样,都是红黑树结构
由键决定特性:不重复、无索引、可排序
可排序:对键进行排序(默认按从小到大,也可以自己指定排序规则)
因此,如果TreeMap结合添加的键值对对象的键是自定义对象时,一定要实现Comparable接口,否则无法进行排序。
书写两种排序规则:
①实现Comparable接口,指定比较规则
②创建集合时传递Coparator比较器对象,指定比较器规则
//方法一:重写Comparable接口的实现类中的CompareTo方法
@Override
public int compareTo(Student o) {
//this表示添加的元素 o表示存在的元素
//返回值小于0放左边,大于0放右边,等于零表示重复元素不存储
//按年龄升序
int i=this.age-o.age;
i=i==0?this.name.compareTo(o.name):i;
return i;
}
//方法二:创建对象时构造comparator比较器对象来制定排序规则
//o1为添加的元素 o2为存在的元素
//返回值小于零放左边,大于放右边,为0表示重复不存储
TreeMap<Integer,String> tm=new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
//降序 return o2-o1;
}
});
六、不可变集合
不可变集合:不可以被修改的集合(内容、长度)
构造方法:
tips:
①若要获取一个不可变的Set集合时,里面的元素要保持唯一性(否则报错)
②若要获取一个不可变的Map集合,键不能重复,且Map.of方法中的参数有上限,最多只能传递20个参数,10个键值对(因为该方法无法用可变参数分别表示key和value)
解决办法:使用另一个方法:Map.ofEntrie 该方法直接传递的是 键值对对象 参数,因此可以使用可变参数。
import java.util.*;
public class Main {
public static void main(String[] args) {
Map<String,String> m=new HashMap<>();
m.put("f","u");
m.put("c","k");
m.put("b","o");
m.put("l","d");
Set<Map.Entry<String ,String>> entries=m.entrySet();
//将集合中所有的键值对对象全部存入 集合对类型的数组arr中
Map.Entry[] arr=entries.toArray(new Map.Entry[0]);
//通过arr 和 ofEntries方法可以实现创建不可变Map集合
Map<String,String> mm=Map.ofEntries(arr);
mm.put("11","111"); //报错
}
}
应用场景:
①某个数据不能被修改,可以防御性的拷贝到不可变集合中
②如果集合对象被不可信的库调用时,不可变形式是安全的
示例代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
//创建不可变集合
List<String> list = List.of("张三", "李四", "王五");
Set<String> set=Set.of("hah","low","bold");//若要获取一个不可变的Set集合时,里面的元素要保持唯一性
//若要获取一个不可变的Map集合,键不能重复,且Map.of方法中的参数有上限,最多只能传递20个参数,10个键值对
Map<String,String> map=Map.of("张三","南京","李四","上海","王五","上海");
for(String e:set){
System.out.println(e);
}
for (String e : list) {
System.out.println(e);
}
for(Map.Entry<String,String> entry:map.entrySet()){
String key=entry.getKey();
String value=entry.getValue();
System.out.println(key+"="+value);
}
System.out.println("__________________________________");
list.remove("李四"); //报错
list.add("张飞"); //报错
list.set(0,"张一"); //报错
System.out.println("___________________________________");
set.remove("李四"); //报错
set.add("张飞"); //报错
System.out.println("___________________________________");
map.put("fuc","fucc"); //报错
}
}