我有一个要求,我想使用Java Stream Api处理来自系统的事件流并应用数据清理过程来删除重复的事件.这是按顺序多次重复删除相同的事件,而不是创建不同事件的列表.大多数在线可用的Java Stream api示例都是从给定输入创建不同的输出.
例如,输入流
[a,b,c,a,a,a,a,d,d,d,c,c,e,e,e,e,e,e,f,f,f]
输出列表或流应该是
[a,b,c,a,d,c,e,f]
我当前的实现(不使用Stream api)看起来像
public class Test { public static void main(String[] args) { String fileName = "src/main/resources/test.log"; try { Listlist = Files.readAllLines(Paths.get(fileName)); LinkedList acc = new LinkedList<>(); for (String line: list) { if (acc.isEmpty()) acc.add(line); else if (! line.equals(acc.getLast()) ) acc.add(line); } System.out.println(list); System.out.println(acc); } catch (IOException ioe) { ioe.printStackTrace(); } } }
输出,
[a, b, c, a, a, a, a, d, d, d, c, c, e, e, e, e, e, e, f, f, f] [a, b, c, a, d, c, e, f]
我已尝试过reduce,groupingBy等各种示例,但没有成功.如果存在这样的可能性,我似乎无法找到将流与我的累加器中的最后一个元素进行比较的方法.
您可以使用IntStream
以获取索引位置List
并使用此优势,如下所示:
Listacc = IntStream .range(0, list.size()) .filter(i -> ((i < list.size() - 1 && !list.get(i).equals(list .get(i + 1))) || i == list.size() - 1)) .mapToObj(i -> list.get(i)).collect(Collectors.toList()); System.out.println(acc);
说明
IntStream.range(0,list.size())
:返回一系列原始int值元素,这些元素将用作访问列表的索引位置.
filter(i -> ((i < list.size() - 1 && !list.get(i).equals(list.get(i + 1) || i == list.size() - 1))
:仅当当前索引位置处的元素不等于下一个索引位置处的元素或者达到最后一个索引位置时才继续
mapToObj(i -> list.get(i)
:将流转换为Stream
.
collect(Collectors.toList())
:将结果收集到列表中.