Java 使用 Stream API 筛选 List
前言
上课的时候看到老师用迭代器来遍历 List 中的元素的时候,我的内心是极其嫌弃的,这种迭代方法不能直接访问当前的元素,而且写起来也麻烦。于是上网查了查 Java 有没有类似于 Linq 的东西,虽然发现了一个 JLinq 但是抱着学习的心态,还是没有用这个东西。看了看 Intellji 的自动补全然后想出了下面的代码。
题目
删除 List 中信息重复的学生
解法一
LinkedList<T3.Student> repo3 = new T3.StudentTest().getRepo();
repo3.removeIf(s->repo3.indexOf(s)!=repo3.lastIndexOf(s));
这个方法看起来是没有很大的问题的,但是如果问题稍微变了一下,这就没用了。
题目 update
删除 List 中信息部分重复的学生,也就是只要姓名、年龄相同的学生就认定为信息重复,即使学号不同。
解法二
上面的解法一到了这个问题就失效了,对于这个问题我只能想到用下面的代码来解决
for (int i = 0; i < repo3.size(); i++)
{
T3.Student stu = repo3.get(i);//Lambda 表达式不允许我用没被引用的变量,所以就把这句单独提了出来
repo3.removeIf(s->s.equals(stu));//根据题意定义的 equals 方法
}
增加了一个 for 循环,其余的基本没变,但是代码的简洁程度相较于使用迭代器得到了大幅度提高。
踩到的坑
0.为毛不用foreach或者forEach循环?
foreach不能适应动态变化的集合,因为我在动作中删除了元素。
forEach虽然是一个内部循环,有并行计算的优势,但是还是由于上面的原因不能使用。
1.Stream 接口的操作不会对原有的数据产生影响。
repo3.removeAll(repo3.stream()
.filter(
s -> repo3.stream().filter(stu -> stu.equals(s)).count() != 0)
.collect(Collectors.toList()));
本来我是想用这种方法拿到所有重复的元素,然而事实上是不行的,因为Stream 接口的操作不会对原有的数据产生影响。导致第二个 filter 会把所有元素重新扫描一遍,所以需要改成下面的代码:
repo3.removeIf
(
s -> repo3
.subList(repo3.indexOf(s),repo3.size())
.stream()
.filter(stu -> stu.equals(s))
.count() != 0
);
看起来好像比解法二复杂了许多但是在效率上有很大的进步,Stream API是并行化的,比外部循环不知道要高到哪里去了,然而这里还存在一个问题,就是在subList中获得对当前元素的索引的速度可能会拖慢效率,然而,在这道题目的测试用例当中学号起到了索引的作用,然后这里的效率可以大幅度提升。
总结
一开始准备用 Stream API 我是拒绝的,我看到它是以方法的形式出现的,我还以为会出现类型转换,后来发现这是 Java 缺少 extend methods 才出现的东西。然后这个东西实现了跟 Linq 差不多的功能,配合 Lambda 表达式很好用。
那么下面给出最终的版本:
repo3.removeIf
(
s -> repo3
.stream()
.filter(stu -> stu.equals(s))
.count() != 0
);
这里之所以不需要把 list 截断可能是因为 removeif也是一个stream方法。
Java 使用 Stream API 筛选 List的更多相关文章
- Java 8 Stream API
Java 8 Stream API JDK8 中有两大最为重要的改变.第一个是 Lambda 式:另外 Stream API(java.util.stream.*) Stream 是 JDK8 中处理 ...
- Java 8 Stream API详解--转
原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java8引入了 ...
- Java 8 Stream API Example Tutorial
Stream API Overview Before we look into Java 8 Stream API Examples, let’s see why it was required. S ...
- Java 8 Stream API具体解释
Java 8 Stream API具体解释 一.Stream API介绍 Java 8引入了全新的Stream API,此Stream与Java I/O包里的InputStream和OutputStr ...
- Java 8 Stream Api 中的 peek 操作
1. 前言 我在Java8 Stream API 详细使用指南[1] 中讲述了 [Java 8 Stream API]( "Java 8 Stream API") 中 map 操作 ...
- Spring WebFlux 学习笔记 - (一) 前传:学习Java 8 Stream Api (2) - Stream的中间操作
Stream API Java8中有两大最为重要的改变:第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*). Stream 是 Java8 中处 ...
- Spring WebFlux 学习笔记 - (一) 前传:学习Java 8 Stream Api (1) - 创建 Stream
影子 在学习Spring WebFlux之前,我们先来了解JDK的Stream,虽然他们之间没有直接的关系,有趣的是 Spring Web Flux 基于 Reactive Stream,他们中都带了 ...
- Java 8 Stream API 详解
Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggregate operation),或者大批量数据操作 (b ...
- Java 8 Stream API 引入和使用
引入流 流是什么 流是Java API的新成员,它允许你以声明性的方式处理数据集合.可以看成遍历数据集的高级迭代.流可以透明地并行处理,无需编写多线程代码.我们先简单看一下使用流的好处.下面两段代码都 ...
随机推荐
- PostgreSQL auto_explain
The auto_explain module provides a means for logging execution plans of slow statements automaticall ...
- From Disk partition to PostgreSQL installation
From Disk partition to PostgreSQLinstallation [root@compute mnt]# fdisk /dev/sdb Welcome to fdisk (u ...
- Leetcode: Range Sum Query 2D - Mutable && Summary: Binary Indexed Tree
Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...
- 某个点到其他点的曼哈顿距离之和最小(HDU4311)
Meeting point-1 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 【Origin】工仕途中
-脚步翩跹,随蝶起舞,翩翩不知所往 晨起脚步催, 蝴蝶迎面飞; 正是春意浓, 三月好风景. -作于二零一六年三月二十八日
- Extjs4.x完美treepanel checkbox无限级选中与取消
注:当node选中, childNodes逐级全部选中. parentNode当子node全部选中时逐级自动选中,nodes未全部选中, parentNode逐级自动取消选中 在javascript中 ...
- 04---Net基础加强
字符串常用方法: 属性: Length获取字符串中字符的个数 IsNullOrEmpty() 静态方法,判断为null或者为“” ToCharArray() 将string转换为char[] To ...
- 夺命雷公狗jquery---2层级选择器
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- zw版【转发·台湾nvp系列例程】halcon与delphi系列例程
zw版[转发·台湾nvp系列例程]halcon与delphi系列例程 台湾nvp技术论坛,是目前halcon与delphi例程最多的网站,也是唯一成系列的, http://zip.nvp.com.tw ...
- opencv常用数据结构之:IplImage
typedef struct_IplImage{ int nSize; //IplImage大小 int ID; //版本(=0) int nChannels; //大多 ...