Map集合
需要存储一一对应的数据时,就可以考虑使用Map集合来做。
- Map集合称为双列集合,格式:{key1=value1 , key2=value2 , key3=value3 , …}, 一次需要存一对数据做为一个元素。
- Map集合的每个元素“key=value”称为一个键值对/键值对对象/Entry对象,Map集合也被叫做“键值对集合”。
- Map集合的所有键是不允许重复的,但值可以重复,键和值是一一对应的,每一个键只能找到自己对应的值。
Map集合体系
Map<K,V>是接口,下面有很多实现类:
- HashMap<K , V>。
- LinkedHashMap<K , V>。(是1的子类。)
- TreeMap<K , V>。
特点:
- Map系列集合的特点都是由键决定的,值只是一个附属品,值是不做要求的。
- HashMap(由键决定特点): 无序、不重复、无索引; (用的最多)。
- LinkedHashMap (由键决定特点):由键决定的特点:有序、不重复、无索引。
- TreeMap (由键决定特点):按照(键的)大小默认升序排序、不重复、无索引。
1 | //经典代码 |
Map常用方法
- public V put(K key,V value)。添加元素。
- public int size()。获取集合的大小。
- public void clear()。清空集合。
- public boolean isEmpty()。判断集合是否为空,为空返回true , 反之。
- public V get(Object key)。根据键获取对应值。
- public V remove(Object key)。根据键删除整个元素。
- public boolean containsKey(Object key)。判断是否包含某个键。(是精确匹配。)
- public boolean containsValue(Object value)。判断是否包含某个值。(值的类型一定要注意。)
- public Set
keySet()。获取全部键的集合。(会放到一个Set里面再返回。) - public Collection
values()。获取Map集合的全部值。(会放到一个Collection里面再返回,因为Set里面不允许有重复的值。) - putAll()。把其他Map集合的数据倒入到自己集合中来。
Map遍历方式
- 键找值。先获取Map集合全部的键,再通过遍历键来找值。
- 键值对。把“键值对“看成一个整体进行遍历(难度较大)。
- Labmda。JDK 1.8开始之后的新技术(非常的简单)。
键找值
- public Set
keySet()。获取所有键的集合。 - public V get(Object key)。根据键获取其对应的值。
1 | // 1、获取Map集合的全部键 |
键值对
使用增强for遍历时,元素类型无法确定。所以Java提供另一个方法:
- Set<Map.Entry<K, V>> entrySet()。获取所有“键值对”的集合。作为一个Set集合返回了,然后每个元素就是键值对类型,自然也就可以遍历了。
Map.Entry提供的方法:
- K getKey()。获取键。
- V getValue()。获取值。
1 | // 1、调用Map集合提供entrySet方法,把Map集合转换成键值对类型的Set集合 |
Labmda(简单,推荐)
JDK 1.8开始。需要用到下面的方法:
- default void forEach(BiConsumer<? super K, ? super V> action)。结合lambda遍历Map集合。
1 | //遍历map集合,传递Lambda表达式 |
(1)HashMap
HashMap(由键决定特点): 无序、不重复、无索引; (用的最多)。
底层原理
- 和HashSet的底层原理一样,基于哈希表实现。实际上:原来学的Set系列集合的底层就是基于Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
- JDK8之前,哈希表 = 数组+链表;JDK8开始,哈希表 = 数组+链表+红黑树;哈希表是一种增删改查数据,性能都较好的数据结构。但是它是无序,不能重复,没有索引支持的(由键决定特点)。
- HashMap的键依赖hashCode方法和equals方法保证键的唯一。
- 如果键存储的是自定义类型的对象,可以通过重写hashCode和equals方法,这样可以保证多个对象内容一样时,HashMap集合就能认为是重复的。
(2)LinkedHashMap
LinkedHashMap (由键决定特点):由键决定的特点:有序、不重复、无索引。
底层原理
- 底层数据结构依然是基于哈希表实现的,只是每个键值对元素又额外的多了一个双链表的机制记录元素顺序(保证有序)。实际上:原来学习的LinkedHashSet集合的底层原理就是LinkedHashMap。
(3)TreeMap
TreeMap (由键决定特点):按照(键的)大小默认升序排序、不重复、无索引。
底层原理
- 特点:不重复、无索引、可排序(按照键的大小默认升序排序,只能对键排序)。
- 原理:TreeMap跟TreeSet集合的底层原理是一样的,都是基于红黑树实现的排序。
- TreeMap集合同样也支持两种方式来指定排序规则。
- 让类实现Comparable接口,重写conpareTo()比较规则。
- TreeMap集合有一个有参数构造器,支持创建Comparator比较器对象,以便用来指定比较规则。
补充知识:集合的嵌套
集合中的元素又是一个集合。
Stream流
JDK8开始最大的改变之一。(一共是两个:1.Lambda表达式,2.Stream流。)
什么是Stream?
- 也叫Stream流,是Jdk8开始新增的一套API (java.util.stream.*),可以用于操作集合或者数组的数据。
- 优势: Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好。
案例
有一个List集合,元素有"张三丰","张无忌","周芷若","赵敏","张强"
,找出姓张,且是3个字的名字,存入到一个新集合中去。
1 | List<String> names = new ArrayList<>(); |
传统方式:
1 | // 找出姓张,且是3个字的名字,存入到一个新集合中去。 |
Stream流:(支持链式编程。)
1 | List<String> list2 = names.stream().filter(s -> s.startsWith("张")).filter(a -> a.length()==3).collect(Collectors.toList()); |
两次filter筛选,然后collect收集。
使用步骤
- 数据源。–>获取其Stream流(理解为流水线,能与数据源建立联系)。
- 中间方法。调用流水线的各种方法对数据进行处理和计算。例如,过滤、排序、去重等。
- 获取结果。便利、统计、收集到一个新的集合中并返回。
1 | 主要掌握下面四点: |
常用方法
获取Stream流
如何获取集合的Stream流?
- Collection类。default Stream
stream()。获取当前集合对象的Stream流。
如何获取数组的Stream流?
- Arrays类。public static
Stream stream(T[] array)。获取当前数组的Stream流。 - Stream类。public static
Stream of(T… values)。获取当前接收数据的Stream流。
1 | /** |
中间方法
中间方法指的是调用完成后会返回新的Stream流,可以继续使用(支持链式编程)。(因此支持链式编程。)
常用方法
- Stream
filter(Predicate<? super T> predicate)。用于对流中的数据进行过滤。 - Stream
sorted()。对元素进行升序排序。 - Stream
sorted(Comparator<? super T> comparator)。对元素进行升序排序。 - Stream
limit(long maxSize)。获取前几个元素。 - Stream
skip(long n)。跳过前几个元素。 - Stream
distinct()。去除流中重复的元素。 Stream map(Function<? super T,? extends R> mapper)。对元素进行加工,并返回对应的新流。 - static
Stream concat(Stream a, Stream b)。合并a和b两个流为一个流。
1 | /** |
终结方法
终结方法指的是调用完成后,不会返回新Stream了,没法继续使用流了。
常用方法
- void forEach(Consumer action)。对此流运算后的元素执行遍历。
- long count()。统计此流运算后的元素个数。
- Optional
max(Comparator<? super T> comparator)。获取此流运算后的最大值元素。 - Optional
min(Comparator<? super T> comparator)。获取此流运算后的最小值元素。
1 | /** |
其他方法
- 收集Stream流。就是把Stream流操作后的结果转回到集合或者数组中去返回。
- Stream流:方便操作集合/数组的手段; 集合/数组:才是开发中的目的。
- R collect(Collector collector)。把流处理后的结果收集到一个指定的集合中去。
- Object[] toArray()。把流处理后的结果收集到一个数组中去。
collect具体的收集方式
- public static
Collector toList()。把元素收集到List集合中。 - public static
Collector toSet()。把元素收集到Set集合中。注意Set会去重。 - public static Collector toMap(Function keyMapper , Function valueMapper)。把元素收集到Map集合中。注意需要在收集的时候指定键和值。而且它不能帮我们去重,因此可能报错,要自己在中间加一个distict()方法。
注意,流只能收集一次!不可以先用一个Steam对象接住Steam流,然后做两次收集操作。