java8 array、list操作 汇【3】)(-Java8新特性之Collectors 详解
//编写一个定制的收集器
public static 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));
}
} public static void main(String[] args){ /* 转载:https://blog.csdn.net/u013291394/article/details/52662761
git: https://github.com/shekhargulati/java8-the-missing-tutorial/tree/master/code */ List<Task> tasks = DataUtils.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()));
} //生成统计信息
IntSummaryStatistics summaryStatistics = tasks.stream().map(Task::getTitle).collect(summarizingInt(String::length));
System.out.println(summaryStatistics.getAverage()); //32.4
System.out.println(summaryStatistics.getCount()); //
System.out.println(summaryStatistics.getMax()); //
System.out.println(summaryStatistics.getMin()); //
System.out.println(summaryStatistics.getSum()); //162 //编写一个定制的收集器
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))); } //Java8中的字数统计
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 AbstractMap.SimpleEntry<>(word, 1))
.collect(groupingBy(AbstractMap.SimpleEntry::getKey, counting()));
wordCount.forEach((k, v) -> System.out.println(String.format("%s ==>> %d", k, v)));
} //将数据收集进一个集合
public static Set<String> uniqueTitles(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(toSet());
}
//将数据收集进一个映射
private static Map<String, Task> taskMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, Function.identity()));
// return tasks.stream().collect(toMap(Task::getTitle, task -> task));
}
//使用toMap方法的另一个变体来处理重复问题,它允许我们指定一个合并方法。这个合并方法允许用户他们指定想如何处理多个值关联到同一个键的冲突。
//在下面展示的代码中,我们只是使用了新的值,当然你也可以编写一个智能的算法来处理冲突。
private static Map<String, Task> taskMap_duplicates(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity(), (t1, t2) -> t2));
}
//可以通过使用toMap方法的第三个变体来指定其他的映射实现。这需要你指定将用来存储结果的Map和Supplier。
public Map<String, Task> collectToMap(List<Task> tasks) {
return tasks.stream().collect(toMap(Task::getTitle, identity(), (t1, t2) -> t2, LinkedHashMap::new));
}
// list<bean> -> Map<String, String>
public class Person {
private Integer id;
private String name;
} import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream; public class Test {
public static void main(String[] args) { List<Person> list = new ArrayList();
list.add(new Person(1, "haha"));list.add(new Person(2, "rere"));list.add(new Person(3, "fefe")); Map<Integer, Person> mapp = list.stream().collect(Collectors.toMap(Person::getId, Function.identity()));
System.out.println(mapp); System.out.println(mapp.get(1).getName()); Map<Integer, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName));
System.out.println(map); }
}
得到的结果:
{1=test.Person@4b9385, 2=test.Person@1311334, 3=test.Person@2a0b20} haha {1=haha, 2=rere, 3=fefe} 来源: https://blog.csdn.net/jiangpingjiangping/article/details/764740
//使用其它的收集器
//像toList和toSet这类特定的收集器不允许你指定内部的列表或者集合实现。当你想要将结果收集到其它类型的集合中时,你可以像下面这样使用toCollection收集器。
private static LinkedHashSet<Task> collectToLinkedHaskSet(List<Task> tasks) {
return tasks.stream().collect(toCollection(LinkedHashSet::new));
}
//找到拥有最长标题的任务
public Task taskWithLongestTitle(List<Task> tasks) {
return tasks.stream().collect(collectingAndThen(maxBy((t1, t2) -> t1.getTitle().length() - t2.getTitle().length()), Optional::get));
}
//统计标签的总数
public int totalTagCount(List<Task> tasks) {
return tasks.stream().collect(summingInt(task -> task.getTags().size()));
}
//生成任务标题的概述
public String titleSummary(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(joining(";"));
} //分类收集器
//例子1:根据类型对任务分类
private static Map<TaskType, List<Task>> groupTasksByType(List<Task> tasks) {
return tasks.stream().collect(groupingBy(Task::getType));
//return tasks.stream().collect(groupingBy(task -> task.getType()));
}
//例子2:根据标签分类
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())));
}
//例子3:根据标签和数量对任务分类
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()));
}
//例子4:根据任务类型和创建日期分类
private static Map<TaskType, Map<LocalDate, List<Task>>> groupTasksByTypeAndCreationDate(List<Task> tasks) {
return tasks.stream().collect(groupingBy(Task::getType, groupingBy(Task::getCreatedOn)));
} //分割
private static Map<Boolean, List<Task>> partitionOldAndFutureTasks(List<Task> tasks) {
return tasks.stream().collect(partitioningBy(task -> task.getDueOn().isAfter(LocalDate.now())));
} //连接所有的标题
private static String allTitles2(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(joining(", "));
}
//将数据收集进一个列表
public static List<String> allTitles(List<Task> tasks) {
return tasks.stream().map(Task::getTitle).collect(toList());
} public static enum TaskType {
READING, CODING, BLOGGING
}
//bean
public static class Task { private LocalDate dueOn; private final String id;
private final String title;
private final String description;
private final TaskType type;
private LocalDate createdOn;
private Set<String> tags = new HashSet<>(); public Task(final String id, final String title, final TaskType type) {
this.id = id;
this.title = title;
this.description = title;
this.type = type;
this.createdOn = LocalDate.now();
} public Task(final String title, final TaskType type) {
this(title, title, type, LocalDate.now());
} public Task(final String title, final TaskType type, final LocalDate createdOn) {
this(title, title, type, createdOn);
} public Task(final String title, final String description, final TaskType type, final LocalDate createdOn) {
this.id = UUID.randomUUID().toString();
this.title = title;
this.description = description;
this.type = type;
this.createdOn = createdOn;
} public LocalDate getDueOn() {
return dueOn;
} public void setDueOn(LocalDate dueOn) {
this.dueOn = dueOn;
} public String getId() {
return id;
} public String getTitle() {
return title;
} public String getDescription() {
return description;
} public TaskType getType() {
return type;
} public LocalDate getCreatedOn() {
return createdOn;
} public Task addTag(String tag) {
this.tags.add(tag);
return this;
} public Set<String> getTags() {
return Collections.unmodifiableSet(tags);
} @Override
public String toString() {
return "Task{" +
"title='" + title + '\'' +
", type=" + type +
'}';
} @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Task task = (Task) o;
return Objects.equals(title, task.title) &&
Objects.equals(type, task.type);
} @Override
public int hashCode() {
return Objects.hash(title, type);
}
}
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;
}
} public static class DataUtils { public static Stream<String> lines() {
return filePathToStream("src/main/resources/book.txt");
} public static Stream<String> negativeWords() {
return filePathToStream("src/main/resources/negative-words.txt");
} public static Stream<String> filePathToStream(String path) {
try {
return Files.lines(Paths.get("training", path));
} catch (IOException e) {
throw new RuntimeException(e);
}
} public static IntStream range(int start, int end) {
return IntStream.rangeClosed(start, end);
} public static List<Task> getTasks() {
Task task1 = new Task("Read Java 8 in action", TaskType.READING, LocalDate.of(2015, Month.SEPTEMBER, 20)).addTag("java").addTag("java8").addTag("books");
Task task2 = new Task("Write factorial program in Haskell", TaskType.CODING, LocalDate.of(2015, Month.SEPTEMBER, 20)).addTag("program").addTag("haskell").addTag("functional");
Task task3 = new Task("Read Effective Java", TaskType.READING, LocalDate.of(2015, Month.SEPTEMBER, 21)).addTag("java").addTag("books");
Task task4 = new Task("Write a blog on Stream API", TaskType.BLOGGING, LocalDate.of(2015, Month.SEPTEMBER, 21)).addTag("writing").addTag("stream").addTag("java8");
Task task5 = new Task("Write prime number program in Scala", TaskType.CODING, LocalDate.of(2015, Month.SEPTEMBER, 22)).addTag("scala").addTag("functional").addTag("program");
return Stream.of(task1, task2, task3, task4, task5).collect(toList());
}
}
java8 array、list操作 汇【3】)(-Java8新特性之Collectors 详解的更多相关文章
- Swift 3 新特性和迁移详解
写在前面 Swift 3.0 正式版发布了差不多快一个月了,断断续续的把手上和 Swift 相关的迁移到了Swift 3.0.所以写点小总结. 背景 代码量(4万行) 首先,我是今年年初才开始入手 S ...
- IOS6 新特性之UIActivityViewController详解
新的IOS6增加了一些新特性.因为应用需要,所以在国庆的几天里.研究了一下IOS6的说明文档,然后大概地总结了一下UIActivityViewController的用法与大家分享. 首先 从实际效果入 ...
- h5新特性 File API详解
之前一直觉得h5的新特性就是一些新标签呢,直到想研究一下图片上传预览的原理,才发现还是有好多新的api的,只是不兼容ie低版本,挺可惜的, File API在表单中文件输入字段基础上,又添加了一些直接 ...
- Android新特性Instant Run详解
关于 Instant Run Android Studio 2.0 中引入的 Instant Run 是 Run 和 Debug 命令的行为,可以大幅缩短应用更新的时间.尽管首次构建可能需要花费较长的 ...
- [C++11新特性] 智能指针详解
动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极为困难的.有时我们会忘记释放内存产生内存泄漏,有时提前释放了内存,再使用指针去引用内存就会报错. 为了更容易(同时也更安全)地使用动态内存, ...
- Spring Boot 2.3 新特性优雅停机详解
什么是优雅停机 先来一段简单的代码,如下: @RestController public class DemoController { @GetMapping("/demo") p ...
- Java8新特性之Collectors
参考:Java8新特性之Collectors 在第二天,你已经学习了Stream API能够让你以声明式的方式帮助你处理集合.我们看到collect是一个将管道流的结果集到一个list中的结束操作.c ...
- Hadoop 新 MapReduce 框架 Yarn 详解
Hadoop 新 MapReduce 框架 Yarn 详解: http://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop-yarn/ Ap ...
- C语言操作WINDOWS系统存储区数字证书相关函数详解及实例
C语言操作WINDOWS系统存储区数字证书相关函数详解及实例 以下代码使用C++实现遍历存储区证书及使用UI选择一个证书 --使用CertOpenSystemStore打开证书存储区. --在循环中 ...
随机推荐
- LICEcap 和 FS Capture入门教程
上一篇介绍了如何使用 Visio 图形图表工具,文中贴了一张gif图,留言的小伙伴们迫不及待想知道如何录制 GIF 图,强哥姑且卖弄一次,把 PC 端截图工具和教程分享给大家,分别为 LICEcap ...
- Leetcode 526
class Solution { public: int countArrangement(int N) { vector<int> nums; ;i <= N;i++) nums. ...
- close_on_exec标志位的作用
转自:http://blog.csdn.net/sunlylorn/article/details/6363727 close_on_exec 是一个进程所有文件描述符(文件句柄)的位图标志,每个比特 ...
- JavaScript学习总结(三)——逻辑And运算符详解
在JavaScript中,逻辑 AND 运算符用双和号(&&)表示 1 var bTrue = true; 2 var bFalse = false; 3 var bResult = ...
- 弹出层小插件之(一)sweetalert
//弹出层小插件之(一)sweetalert 1.引入sweetalert.css 2.引入sweetalert.min.js 下载地址:http://t4t5.github.io/sweetaler ...
- document.write vs document.getElementById
document.write: JavaScript中对document.open所开启的文档流(document stream操作的API方法,它能够直接在文档流中写入字符串,一旦文档流已经关闭,那 ...
- GetTickCount()函数
GetTickCount(),这个函数,在此做下整理和总结.1.定义For Release configurations, this function returns the number of mi ...
- Bat脚本:通过端口号查找进程号
最近在用jenkins做自动化web部署,web服务器是tomcat. 遇到了这样一个问题:在服务器上执行tomcat的shutdown.bat命令可以正常关机,但用jenkins执行shutdown ...
- 2018-北航-面向对象第三次OO作业分析与小结
1. 规格设计的发展历史 规格设计用于对程序设提供分解,抽象等的手段.在撰写代码规格的时候,需要对组成部件进行抽象. 在1960s,软件设计出现危机,例如Dijkstra提出了goto语句的种种危害, ...
- 组件的 keep-alive 简介
本篇文章,我们来讲一下keep-alive的实现. 更容易看懂 Vue中,有三个内置的抽象组件,分别是keep-alive.transition和transition-group, 它们都有一个共同 ...