一、Map映射
映射用来存放键/值对,如果提供了键就可以查找到值。需要注意的是Map集合并未继承Collection
1、映射的基本操作
映射有两个实现类:TreeMap、HashMap。这两个类均实现了Map接口。散列映射对键进行散列,而树映射根据键的顺序将元素组织为一个搜索树。
键必须是唯一的。不能一个键同时存放两个值,如果对同一个键连续调用两次put方法,第二值会取代第一个值。
Java.util.Map<K,V>
- V get(Object key) //获取与键关联的值,若没有该值则返回null
- default V getOrDefault(Object key,V defaultValue)
//获取与键关联的值,若没有该值则返回defaultValue
- V put(K ket,V value) //存放键值对,若键存在则覆盖原来的键值对
- boolean containKey(Object key) //若键存在返回true
- boolean containValue(Object value) //若值存在返回true
- default void forEach(BiConsumer<? super K,? super V >action)
//对于映射的所有键值对均应用这个动作
例、构建一个散列映射,测试各种方法,利用forEach方法并构造lambda表达式遍历访问
package cn.Map;
import javax.swing.*;
import java.util.HashMap;
import java.util.Map;
/**
* <h3>idea_test</h3>
* <p>映射学习</p>
*
* @author nb
* @date 2023-01-14 11:32
**/
public class TestMap {
public static void main(String args[])
{
//构建一个散列映射类,添加键值对
Map<Integer, String> map = new HashMap<>();
map.put(1,"a");
map.put(2,"b");
map.put(3,"c");
//直接使用println输出
System.out.println(map);
//删除键值对
map.remove(1);
//对同一个键调用两次put方法,覆盖原本键值对的值
map.put(1,"d");
//get方法获取键所对应的值
System.out.println(map.get(1));
//使用forEach实现遍历,此时利用lambda表达式实现,参数为k,v
map.forEach((k,v)->{System.out.println("key="+k+",value="+v);});
}
}
2、更新映射条目
1、调用putIfAbsent方法,只有当键原先存在时才会放入有一个值。
putIfAbsent() 方法会先判断指定的键(key)是否存在,不存在则将键/值对插入到 HashMap 中。
返回值:当key存在时返回key所对应的value,, 如果所指定的 key 不在 HashMap 中存在,则返回 null。
2、merge方法
merge() 方法会先判断指定的 key 是否存在,如果不存在,则添加键值对到 hashMap 中。
语法结构:
map.merge(key,value,remappingFunction)
其中remappingFunction为重新映射函数,用于重新计算值
返回值:
如果 key 对应的 value 不存在,则返回该 value 值,如果存在,则返回通过 remappingFunction 重新计算后的值。当key对应的value不存在时,通过映射函数所计算的新值插入到key所对应的位置。
例、依以上例子对putIfAbsent方法、merge方法测试
//利用putIfAbsent方法,方法会先判断指定的键(key)是否存在,不存在则将键/值对插入到 HashMap 中。
//当key 为 1已经存在于 map 中,所以不会执行插入操作。
//当key存在,则返回key所对应的value
System.out.println(map.putIfAbsent(1,"f"));
//merge方法返回:当key存在返回value的值,若不存在返回根据remappingFunction方法重新计算后的值。
System.out.println(map.merge(1,"c",(k,v)->k+v));
System.out.println(map);
3、映射视图
集合框架不认为映射是一个集合,不过可以得到映射的视图(view),来实现了Collection接口或某个子接口的对象。
有三种视图:键集、值集合、键/值对集
Set<K> keySet()
Collection<V> values()
Set<Map.Entry<K,V>> entrySet()
需要说明的是keySet()返回的不是HashSet、TreeSet而是实现了Set接口的另外一个对象。Set接口扩展了Collection接口,所以可以像任意集合一样使用keySet。
4、链接散列集与映射
LinkedHashSet、LinkedHashMap类会记住插入元素的顺序。以此来避免散列表中的项看起来是随机的。在表中插入元素项时,就会并入到双向链表中。
5、枚举集与映射
//
二、视图与包装器
可以使用视图(view)获得其他实现了Collection接口与Map接口的对象。例如keySet方法返回了一个实现了Set接口的类对象,由这种类操作原映射,这种集合称为视图。
1、小集合
Java9引入了新的静态方法,可以生成给定元素的集或列表,以及给定键/对的映射。
List<String> list = List.of("a","b","c"); Set<Integer> set = Set.of(1,2,3); Map<Integer,String> map = Map.of(1,"a",2,"b",3,"c");
元素,键值不能为null。这些集合的对象是不可修改的,如果需要一个可更改的集合则需要把这个不可修改的集合传入到构造器中。
var abc = new ArrayList<>(List.of("a","b","c"));
Collection.nCopies(n,anObject);
Collection.nCopies(100,"DEFAULT")
//这个方法可以将包含100个字符串都设置为DEFAULT
例、使用of方法构建后,无法修改其值,若修改则抛出UnsupportedOperationException。
个人理解:小集合是对元素较少的时一种很好的处理方式。
2、子范围
与Sting.substring一样,子范围区间为左闭右开。列表子范围(subList)且操作会反映到整个列表
例、先将list转换为可改变的temp,[0,2),取第一个与第二个元素,并删除子范围查看原list是否发生改变
//先将list转换为可改变的temp,[0,2),取第一个与第二个元素,并删除子范围查看原list是否发生改变
List<String> list = List.of("a","b","c");
var temp = new LinkedList<>(list);
List<String> list1 = temp.subList(0,2);
list1.clear();
cn.SetCollection.Queue.echo_(temp);
可以发现子范围的操作会影响到原列表
例2、对有序映射进行取子范围,也为左闭右开
//对于有序映射,可以使用subMap(K from,K to)方法获取子范围
var map1 = new TreeMap<>(map);
System.out.println(map1.subMap(1,3));
其列表、集、映射具体获取获取子范围方法见下表
三、栈
栈是一种后进先出的数据结构,Stack类扩展了Vector类
- E push(E item) //将item压入栈并返回item
- E pop() //弹出栈顶的item
- E peek() //返回栈顶元素,但不弹出