最近接触到java8的collector功能,网上查了下资料学习,这里记录一下。
collect
方法,它是一个能够把stream管道中的结果集装进一个List
集合的终极操作。 collect
是一个把stream规约成一个value的规约操作,这里的value可以是一个Collection、Map或者一个value对象。在下面这几种情况下,可以使用collect
操作。
-
把stream规约到一个单独的值 stream的执行结果可以规约成一个单独的值,这个单独的值可以是
Collection
或者数值型的值如int、double等,还可以是一个自定义的值对象。 -
在stream中对元素进行分组 对stream中的所有task按照TaskType分组。这会生成一个一个
Map<TaskType,List<Task>
,其中的每个entry都包含一个TaskType和与它相关联的Task。也可以使用其它任何的Collection来替代List。如果不需要把所有的task对应到一个TaskType,也可以生成一个Map<TaskType,Task>
。 -
分离stream中的元素 可以把一个stream分离到两个组中--正在进行中的和已经完成的task。
1 Collector in Action
下面我们通过这个根据type来对task进行分组的例子,来体验Collector
的作用。在java8中,我们可以像下面这样来实现根据TaskType分组。请参考博客day 2
private static Map<TaskType, List<Task>> groupTasksByType(List<Task> tasks) {
return tasks.stream().collect(Collectors.groupingBy(task -> task.getType()));
}
上面的代码使用了Collectors
工具类中定义的groupingBy
Collector
方法。它创建一个map,其中key为TaskType
、value为所有具有相同TaskType
的task组成的一个list列表。在java7中要实现相同的功能,需要写如下的代码。
public static void main(String[] args) {
List<Task> tasks = getTasks();
Map<TaskType, List<Task>> allTasksByType = new HashMap<>();
for (Task task : tasks) {
List<Task> existingTasksByType = allTasksByType.get(task.getType());
if (existingTasksByType == null) {
List<Task> tasksByType = new ArrayList<>();
tasksByType.add(task);
allTasksByType.put(task.getType(), tasksByType);
} else {
existingTasksByType.add(task);
}
}
for (Map.Entry<TaskType, List<Task>> entry : allTasksByType.entrySet()) {
System.out.println(String.format("%s =>> %s", entry.getKey(), entry.getValue()));
}
}
2 收集器(Collectors):常用规约操作
Collectors
工具类提供了许多静态工具方法来为大多数常用的用户用例创建收集器,比如将元素装进一个集合中、将元素分组、根据不同标准对元素进行汇总等。本文中将覆盖大多数常见的收集器(Collector)
。
2.1 规约到一个单独的值
如上面所说,收集器(collector)可以用来把stream收集到一个collection中或者产生一个单独的值。
2.1.1 把数据装进一个list列表中
下面我们给出第一个测试用例--将给定的任务列表的所有标题收集到一个List列表中。
import static java.util.stream.Collectors.toList;
public class Example2_ReduceValue {
public List<String> allTitles(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(toList());
}
}
toList
收集器通过使用List的add
方法将元素添加到一个结果List列表中,toList
收集器使用ArrayList
作为List的实现。
2.1.2 将数据收集到一个Set中
如果要保证所收集的title不重复并且我们对数据的排序没有要求的话,可以采用toSet
收集器。
import static java.util.stream.Collectors.toSet;
public Set<String> uniqueTitles(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(toSet());
}
toSet
方法采用HashSet
作为Set的实现来储存结果集。
2.1.3 把数据收集到一个Map中
可以使用toMap
收集器将一个stream转换成一个Map。toMap
收集器需要两个集合函数来提取map中的key和value。下面的代码中,Task::getTitle
需要一个task并产生一个仅有一个标题的key。task -> task是一个用来返回自己的lambda表达式,上例中返回一个task。
private static Map<String, Task> taskMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, task -> task));
}
可以使用Function
接口中的默认方法identity
来让上面的代码代码变得更简洁明了、传递开发者意图时更加直接,下面是采用identity函数的代码。
import static java.util.function.Function.identity;
private static Map<String, Task> taskMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity()));
}
代码创建了一个Map,当出现相同的key时就会抛出如下的异常。
Exception in thread "main" java.lang.IllegalStateException:
Duplicate key Task{title='Read Version Control with Git book', type=READING}
at java.util.stream.Collectors.lambda$throwingMerger$105(Collectors.java:133)
toMap
还有一个可以指定合并函数的变体,我们可以采用它来处理重复的副本。合并函数允许开发者指定一个解决同一个key冲突的规则。在下面的代码中,我们简单地使用最后一个value,当然你也可以写更加智能的算法来处理冲突。
private static Map<String, Task> taskMap_duplicates(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity(), (t1, t2) -> t2));
}
我们还可以使用toMap
的第三种变体方法来使用任何其它的Map实现,这需要指定Map
和Supplier
来存放结果。
public Map<String, Task> collectToMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity(), (t1, t2) -> t2, LinkedHashMap::new));
}
与toMap
收集器类似,toConcurrentMap
收集器可以产生ConcurrntMap
来替代HashMap
。
3 Using other collections 使用其它的集合
toList
和toSet
等特定的收集器不支持指定潜在的list或set的实现,当你想要像下面这样这样把结果聚合到其它类型的集合时可以采用toCollection
收集器。
private static LinkedHashSet<Task> collectToLinkedHaskSet(List<Task> tasks) {
return tasks.stream().collect(toCollection(LinkedHashSet::new));
}
找出标题最长的task
public Task taskWithLongestTitle(List<Task> tasks) {
return tasks.stream().collect(collectingAndThen(maxBy((t1, t2) -> t1.getTitle().length() - t2.getTitle().length()), Optional::get));
}
统计tags的总数
public int totalTagCount(List<Task> tasks) {
return tasks.stream().collect(summingInt(task -> task.getTags().size()));
}
生成task标题的汇总
import static java.util.stream.Collectors.joining;
public String titleSummary(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(joining(";"));
}
将元素分组
Collector收集器一个最常见的用户用例就是对元素进行分组,下面我们通过几个示例来理解我们可以如何来分组。
Example 1: 根据type对tasks分组
下面这个例子,我们根据TaskType
对task进行分组。通过使用Collectors
工具类的groupingBy
收集器,我们可以非常简单的完成这个功能。可以使用方法引用和静态引入来让代码变得更加简洁。
import static java.util.stream.Collectors.groupingBy;
private static Map<TaskType, List<Task>> groupTasksByType(List<Task> tasks) {
return tasks.stream().collect(groupingBy(Task::getType));
}
会产生如下的输出:
{
CODING=[
Task{title='Write a mobile application to store my tasks', type=CODING, createdOn=2015-07-03}],
WRITING=[Task{title='Write a blog on Java 8 Streams', type=WRITING, createdOn=2015-07-04}],
READING=[Task{title='Read Version Control with Git book', type=READING, createdOn=2015-07-01},
Task{title='Read Java 8 Lambdas book', type=READING, createdOn=2015-07-02},
Task{title='Read Domain Driven Design book', type=READING, createdOn=2015-07-05}
]
}
Example 2: 根据tags分组
private static Map<String, List<Task>> groupingByTag(List<Task> tasks) {
return tasks.stream().
flatMap(task -> task.getTags().stream().map(tag -> new TaskTag(tag, task))).
collect(groupingBy(TaskTag::getTag, mapping(TaskTag::getTask,toList())));
}
private static class TaskTag {
final String tag;
final Task task;
public TaskTag(String tag, Task task) {
this.tag = tag;
this.task = task;
}
public String getTag() {
return tag;
}
public Task getTask() {
return task;
}
}
Example 3: 根据tag和tag的个数分组
private static Map<String, Long> tagsAndCount(List<Task> tasks) {
return tasks.stream().
flatMap(task -> task.getTags().stream().map(tag -> new TaskTag(tag, task))).
collect(groupingBy(TaskTag::getTag, counting()));
}
Example 4: 根据TaskType和createdOn分组
private static Map<TaskType, Map<LocalDate, List<Task>>> groupTasksByTypeAndCreationDate(List<Task> tasks) {
return tasks.stream().collect(groupingBy(Task::getType, groupingBy(Task::getCreatedOn)));
}
分割
有时候,你需要根据一定的规则将一个数据集分成两个数据集。比如,我们可以定义一个分割函数,根据规则进行时间早于今天和进行时间晚于今天
将task分成两组。
private static Map<Boolean, List<Task>> partitionOldAndFutureTasks(List<Task> tasks) {
return tasks.stream().collect(partitioningBy(task -> task.getDueOn().isAfter(LocalDate.now())));
}
生成统计
另外,一些产生统计结果的收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。
IntSummaryStatistics summaryStatistics = tasks.stream().map(Task::getTitle).collect(summarizingInt(String::length));
System.out.println(summaryStatistics.getAverage()); //32.4
System.out.println(summaryStatistics.getCount()); //5
System.out.println(summaryStatistics.getMax()); //44
System.out.println(summaryStatistics.getMin()); //24
System.out.println(summaryStatistics.getSum()); //162
还有一些其它的基本类型的变体,比如LongSummaryStatistics
和 DoubleSummaryStatistics
还可以用combine
操作来把两个IntSummaryStatistics
结合到一起。
firstSummaryStatistics.combine(secondSummaryStatistics);
System.out.println(firstSummaryStatistics)
把所有的titles连在一起
import static java.util.stream.Collectors.joining;
private static String allTitles(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(joining(", "));
}
编写一个自定义的收集器
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
public class MultisetCollector<T> implements Collector<T, Multiset<T>, Multiset<T>> {
@Override
public Supplier<Multiset<T>> supplier() {
return HashMultiset::create;
}
@Override
public BiConsumer<Multiset<T>, T> accumulator() {
return (set, e) -> set.add(e, 1);
}
@Override
public BinaryOperator<Multiset<T>> combiner() {
return (set1, set2) -> {
set1.addAll(set2);
return set1;
};
}
@Override
public Function<Multiset<T>, Multiset<T>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
}
}
import com.google.common.collect.Multiset;
import java.util.Arrays;
import java.util.List;
public class MultisetCollectorExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("shekhar", "rahul", "shekhar");
Multiset<String> set = names.stream().collect(new MultisetCollector<>());
set.forEach(str -> System.out.println(str + ":" + set.count(str)));
}
}
Word Count in Java 8 Java8中的单词统计
下面,我们通过java8中的Streams和Collectors编写一个非常著名的单词统计示例来结束本文。
public static void wordCount(Path path) throws IOException {
Map<String, Long> wordCount = Files.lines(path)
.parallel()
.flatMap(line -> Arrays.stream(line.trim().split("\\s")))
.map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase().trim())
.filter(word -> word.length() > 0)
.map(word -> new SimpleEntry<>(word, 1))
.collect(groupingBy(SimpleEntry::getKey, counting()));
wordCount.forEach((k, v) -> System.out.println(String.format("%s ==>> %d", k, v)));
}
例子
Hosting.java
package com.mkyong.java8
public class Hosting {
private int Id;
private String name;
private long websites;
public Hosting(int id, String name, long websites) {
Id = id;
this.name = name;
this.websites = websites;
}
//getters, setters and toString()
}
1. List 转换为 Map – Collectors.toMap()
创建 Hosting 的list,使用
Collectors.toMap
转换为 Map.
TestListMap.java
package com.mkyong.java8
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TestListMap {
public static void main(String[] args) {
List<Hosting> list = new ArrayList<>();
list.add(new Hosting(1, "liquidweb.com", 80000));
list.add(new Hosting(2, "linode.com", 90000));
list.add(new Hosting(3, "digitalocean.com", 120000));
list.add(new Hosting(4, "aws.amazon.com", 200000));
list.add(new Hosting(5, "mkyong.com", 1));
// key = id, value - websites
Map<Integer, String> result1 = list.stream().collect(Collectors.toMap(Hosting::getId, Hosting::getName));
System.out.println("Result 1 : " + result1);
// key = name, value - websites
Map<String, Long> result2 = list.stream().collect(Collectors.toMap(Hosting::getName, Hosting::getWebsites));
System.out.println("Result 2 : " + result2);
// Same with result1, just different syntax
// key = id, value = name
Map<Integer, String> result3 = list.stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getName()));
System.out.println("Result 3 : " + result3);
}
}
输出:
Result 1 : {1=liquidweb.com, 2=linode.com, 3=digitalocean.com, 4=aws.amazon.com, 5=mkyong.com}
Result 2 : {liquidweb.com=80000, mkyong.com=1, digitalocean.com=120000, aws.amazon.com=200000, linode.com=90000}
Result 3 : {1=liquidweb.com, 2=linode.com, 3=digitalocean.com, 4=aws.amazon.com, 5=mkyong.com}
附加类型转换:int-->string
numbers.stream().map(number -> String.valueOf(number)).collect(Collectors.joining(", "))
public static void main(String[] argv) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
System.out.println(numbers.stream().map(number -> String.valueOf(number)).collect(Collectors.joining(", ")));
}
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
StringBuilder b = new StringBuilder();
list.forEach(b::append);
System.out.println(b);
//或者
String s = list.stream().map(Object::toString).collect(Collectors.joining(","));
2. List to Map – Duplicated Key!
2.1 运行下面代码,重复key会报错!
TestDuplicatedKey.java
package com.mkyong.java8;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TestDuplicatedKey {
public static void main(String[] args) {
List<Hosting> list = new ArrayList<>();
list.add(new Hosting(1, "liquidweb.com", 80000));
list.add(new Hosting(2, "linode.com", 90000));
list.add(new Hosting(3, "digitalocean.com", 120000));
list.add(new Hosting(4, "aws.amazon.com", 200000));
list.add(new Hosting(5, "mkyong.com", 1));
list.add(new Hosting(6, "linode.com", 100000)); // new line
// key = name, value - websites , but the key 'linode' is duplicated!?
Map<String, Long> result1 = list.stream().collect(Collectors.toMap(Hosting::getName, Hosting::getWebsites));
System.out.println("Result 1 : " + result1);
}
}
输出– 报错:
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 90000
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1245)
//...
2.2 解决重复key问题,传递处理函数参数:
Map<String, Long> result1 = list.stream().collect(
Collectors.toMap(Hosting::getName, Hosting::getWebsites, (oldValue, newValue) -> oldValue)
);
输出:
Result 1 : {..., aws.amazon.com=200000, linode.com=90000}
注意:(oldValue, newValue) -> oldValue
==> 如果key重复,使用oldKey
3.3 尝试使用newValue
Map<String, Long> result1 = list.stream().collect(
Collectors.toMap(Hosting::getName, Hosting::getWebsites,(oldValue, newValue) -> newvalue)
);
输出:
Result 1 : {..., aws.amazon.com=200000, linode.com=100000}
3. List to Map – Sort & Collect
TestSortCollect.java
package com.mkyong.java8;
import java.util.*;
import java.util.stream.Collectors;
public class TestSortCollect {
public static void main(String[] args) {
List<Hosting> list = new ArrayList<>();
list.add(new Hosting(1, "liquidweb.com", 80000));
list.add(new Hosting(2, "linode.com", 90000));
list.add(new Hosting(3, "digitalocean.com", 120000));
list.add(new Hosting(4, "aws.amazon.com", 200000));
list.add(new Hosting(5, "mkyong.com", 1));
list.add(new Hosting(6, "linode.com", 100000));
//example 1
Map result1 = list.stream()
.sorted(Comparator.comparingLong(Hosting::getWebsites).reversed())
.collect(
Collectors.toMap(
Hosting::getName, Hosting::getWebsites, // key = name, value = websites
(oldValue, newValue) -> oldValue, // if same key, take the old key
LinkedHashMap::new // returns a LinkedHashMap, keep order
));
System.out.println("Result 1 : " + result1);
}
}
Result 1 : {aws.amazon.com=200000, digitalocean.com=120000, linode.com=100000, liquidweb.com=80000, mkyong.com=1}
P.S
上面例子中, stream在collect前已经被排序了, 所以“linode.com=100000” 已经成为 ‘oldValue’.
枚举例子使用
public enum MyCodeEnum {
ERR_1 ("1", "1 error"),
ERR_2 ("2", "2 error");
private String code;
private String message;
MyCodeEnum(String c, String m) {
code = c;
message = m;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
@Override
public String toString(){
return "{code:\""+this.code + "\",message:\"" + this.message + "\"}";
}
public Map<String, String> toHashMap(){
return new HashMap<String, String>(){{
put("code", code);
put("message", message);
}};
}
/* Reverse Lookup Implementation */
private static final Map<String, Map<String, String>> lookup
= Arrays.asList(values()).stream().collect(toMap(MyCodeEnum::getCode, MyCodeEnum::toHashMap));
public static Map<String, String> getMapValue(String aKey) {
return lookup.get(aKey);
}
private static final Map<String, String> lookup2
= Arrays.asList(values()).stream().collect(toMap(MyCodeEnum::getCode, MyCodeEnum::getMessage));
public static boolean containsKey(String aKey) {
return lookup2.containsKey(aKey);
}
public static String getKeyValue(String aKey) {
return lookup2.get(aKey);
}
}
上面例子中:
Arrays.asList(values())是枚举初始化时将所有枚举都组合成一个list。
Java program to convert `List<Integer>` to `List<String>`
List<String> newList = list.stream()
.map(s -> String.valueOf(s))
.collect(Collectors.toList());
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
// Java program to convert `List<Integer>` to `List<String>`
class Main
{
// Program to convert `List<Integer>` to `List<String>`
public static void main(String[] args)
{
List<Integer> list = Arrays.asList( 1, 2, 3, 4, 5 );
List<String> newList = list.stream()
.map(s -> String.valueOf(s))
.collect(Collectors.toList());
System.out.println(newList);
}
}
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
// Java program to convert `List<Integer>` to `List<String>`
class Main
{
// Generic method to convert `List<Integer>` to `List<String>`
public static <T, U> List<U> transform(List<T> list,
Function<T, U> function)
{
return list.stream()
.map(function)
.collect(Collectors.toList());
}
// Program to convert `List<Integer>` to `List<String>`
public static void main(String[] args)
{
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<String> newList = transform(list, String::valueOf);
System.out.println(newList);
}
}
#############################
Java stream流 修改List<String> 和 List<对象>
list.stream().filter(dto-> 筛选条件).forEach(dto2-> dto2.setId("1"));
/**
* List<String> 无法for循环修改 用jdk8新特性 stream流
* */
List<String> list = Arrays.asList("1" , "1" ,"1" ,"1" ,"1" ,"1");
// 给 list 元素都添加 2 标识
System.out.println(list.stream().map(x -> x + 2).collect(Collectors.toList()));
输出:[12, 12, 12, 12, 12, 12]
修改对象:
List<DataX> dataXES = JSON.parseArray(payload, DataX.class);
//dataXES = dataXES.stream().peek(x -> x.setTss("11111"))).collect(Collectors.toList());
dataXES = dataXES.stream().peek(x -> {x.setTss("11111"); x.setTss2("22222");})).collect(Collectors.toList());
System.out.println(dataXES);
###########################################
java8 list.forEach() 修改值失败
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User("bb"));
list.forEach(u -> {
u.setName("aaa");
});
System.out.println(list);
List<String> list2 = new ArrayList<>();
list2.add("bb");
list2.forEach(u -> {
u = "aaa";
});
System.out.println(list2);
List<String[]> list3 = new ArrayList<>();
list3.forEach(arr -> {
arr = new String[]{"aaa"};
});
System.out.println(list3);
}
}
结果
[User(name=aaa)]
[bb]
[]
原因
list.forEach掉的底层是ArrayList的forEach
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
final E[] elementData = (E[]) this.elementData; 做了传参,然后把赋予的参数带到了action.accept(elementData[i]);中执行
如果是String、String[] 等基础类型,就会是值传递,导致后续的赋值失败
如果是引用对象类型,则传递得是引用,赋值会成功
#############################################
Map 转另一个Map
//示例1 Map<String, List<String>> 转 Map<String,User>
Map<String,List<String>> map = new HashMap<>();
map.put("java", Arrays.asList("1.7", "1.8"));
map.entrySet().stream();
@Getter
@Setter
@AllArgsConstructor
public static class User{
private List<String> versions;
}
Map<String, User> collect = map.entrySet().stream()
.collect(Collectors.toMap(
item -> item.getKey(),
item -> new User(item.getValue())));
//示例2 Map<String,Integer> 转 Map<String,Double>
Map<String, Integer> pointsByName = new HashMap<>();
Map<String, Integer> maxPointsByName = new HashMap<>();
Map<String, Double> gradesByName = pointsByName.entrySet().stream()
.map(entry -> new AbstractMap.SimpleImmutableEntry<>(
entry.getKey(), ((double) entry.getValue() /
maxPointsByName.get(entry.getKey())) * 100d))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
stream流 转 Map中
假设有一个User实体类,有方法getId(),getName(),getAge()等方法,示例如下:
Stream<User> userStream = Stream.of(new User(0, "张三", 18), new User(1, "张四", 19), new User(2, "张五", 19), new User(3, "老张", 50));
Map<Integer, User> userMap = userSteam.collect(Collectors.toMap(User::getId, item -> item));
字典查询和数据转换 toMap时,如果value为null,会报空指针异常
解决办法一:
Map<String, List<Dict>> resultMaps = Arrays.stream(dictTypes) .collect(Collectors.toMap(i -> i, i -> Optional.ofNullable(dictMap.get(i)).orElse(new ArrayList<>()), (k1, k2) -> k2));
解决办法二:
Map<String, List<Dict>> resultMaps = Arrays.stream(dictTypes) .filter(i -> dictMap.get(i) != null).collect(Collectors.toMap(i -> i, dictMap::get, (k1, k2) -> k2));
解决办法三:
Map<String, String> memberMap = list.stream().collect(HashMap::new, (m,v)-> m.put(v.getId(), v.getImgPath()),HashMap::putAll); System.out.println(memberMap);
解决办法四:
Map<String, String> memberMap = new HashMap<>(); list.forEach((answer) -> memberMap.put(answer.getId(), answer.getImgPath())); System.out.println(memberMap); Map<String, String> memberMap = new HashMap<>(); for (Member member : list) { memberMap.put(member.getId(), member.getImgPath()); }
#############################################
新特性Stream
Stream语法讲解
Stream执行流程很简单,主要有三个,首先创建一个Stream,然后使用Stream操作数据,最后终止Stream。有点类似于Stream的生命周期。下面我们根据其流程来一个一个讲解。
1、前提准备
首先我们创建一个Student类,以后我们每次都是操作这个类
然后下面我们再创建一个StudentData类,用于获取其数据
我们只需要把方法变成static类型的就可以了。
2、创建一个Stream
方式一:通过一个集合创建Stream
方式二:通过一个数组创建Stream
方式三:通过Stream.of
方式四:创建一个无限流
3、使用Stream操作数据
操作1:筛选和切片
操作2:映射
操作3:排序
4、终止Stream
操作1:匹配和查找
操作2:归约
操作3:收集
stream基本的语法就是这样,你会发现Stream就像是一个工具一样,可以帮我们分析处理数据,极其的好用,但是目前还不知道其效率如何。根据网上一位大佬的内存时间分析,其实在数据量比较庞大的时候,Stream可以为我们节省大量的时间,数据量小的时候并不明显
参考
- Java 8 Collectors JavaDoc
- Java 8 – How to sort a Map
- Java 8 Lambda : Comparator example
- 【译】java8之collector - 简书
- Java 8 - Convert List to Map - Mkyong.com
- https://www.cnblogs.com/hiver/p/9156147.html
请我喝咖啡
如果觉得文章写得不错,能对你有帮助,可以扫描我的微信二维码请我喝咖啡~~哈哈~~