Java8 流中的惰性排序(),需要在每次迭代时求助
Lazy sorted() in Java8 Streams, need for resorting at each iteration
我正在寻找一种使用 Java 8 个流模拟以下行为的方法。
给定一系列年份,对它们进行排序,以便输出前 10 个值,这样
输出一年后,减少并再次重新开始迭代:
如果我输入 2005 年、2020 年、2000 年、1967 年和 2018 年,我希望在 10 的限制下得到以下结果:
2020
2019
2018 2018
2017 2017
2016 2016 2016
2015 ...
我使用的测试是:
public class LazyTest {
public static void main(String[] args) {
Stream.of(2005,2020,2000,1967,2018)
.map(YearWrapper::new)
.sorted()
.limit(10)
.peek(year -> year.decreaseYear())
.forEach(System.out::println);
}
public static class YearWrapper implements Comparable<YearWrapper>{
private int currentYear;
public YearWrapper(int year){
this.currentYear=year;
}
public void decreaseYear(){
currentYear--;
}
@Override
public int compareTo(YearWrapper yearsToCompare) {
return Integer.compare(yearsToCompare.currentYear, this.currentYear);
}
@Override
public String toString(){
return String.valueOf(currentYear);
}
}
}
不过看起来sorted()一点也不偷懒。整个排序在开始时完成一次,因此在任何进一步操作之前计算顺序,因此,示例的 5 个值按顺序逐一传递,因此 decrease() 对迭代没有实际影响。
有没有什么办法可以让 sorted() 变得懒惰并在流式传输下一个元素之前再次应用于剩余元素?
任何其他关闭方法将不胜感激!!
我对你的理解是否正确,你想从列表中取出最大的数字,递减它,把它放回列表中,重复 10 次?
如果是,那么这是 PriorityQueue 的工作:
PriorityQueue<Integer> queue = Stream.of(2005,2020,2000,1967,2018)
.collect(toCollection(() -> new PriorityQueue(reverseOrder())));
Stream.generate(() -> {
Integer year = queue.poll();
queue.add(year - 1);
return year;
}).limit(10).forEach(System.out::println);
documentation of Stream.sorted()
说:
This is a stateful intermediate operation.
这又是described as
Stateful operations may need to process the entire input before producing a result. For example, one cannot produce any results from sorting a stream until one has seen all elements of the stream.
这说明了排序的非惰性性质,但是,这与您的问题无关。即使排序是惰性的,也没有改变流的基本原则,即每个项目被流式传输到终端操作最多一次。
您说您希望排序“懒惰”,但您实际期望的是在消费后对每个项目再次进行排序,这意味着对 n[=28 的流进行排序=] 元素意味着实际排序 n 项 n 次,这是其他人不会想到的,特别是因为 peek
并不意味着影响正在进行的操作的副作用。
我正在寻找一种使用 Java 8 个流模拟以下行为的方法。 给定一系列年份,对它们进行排序,以便输出前 10 个值,这样 输出一年后,减少并再次重新开始迭代:
如果我输入 2005 年、2020 年、2000 年、1967 年和 2018 年,我希望在 10 的限制下得到以下结果:
2020
2019
2018 2018
2017 2017
2016 2016 2016
2015 ...
我使用的测试是:
public class LazyTest {
public static void main(String[] args) {
Stream.of(2005,2020,2000,1967,2018)
.map(YearWrapper::new)
.sorted()
.limit(10)
.peek(year -> year.decreaseYear())
.forEach(System.out::println);
}
public static class YearWrapper implements Comparable<YearWrapper>{
private int currentYear;
public YearWrapper(int year){
this.currentYear=year;
}
public void decreaseYear(){
currentYear--;
}
@Override
public int compareTo(YearWrapper yearsToCompare) {
return Integer.compare(yearsToCompare.currentYear, this.currentYear);
}
@Override
public String toString(){
return String.valueOf(currentYear);
}
}
}
不过看起来sorted()一点也不偷懒。整个排序在开始时完成一次,因此在任何进一步操作之前计算顺序,因此,示例的 5 个值按顺序逐一传递,因此 decrease() 对迭代没有实际影响。
有没有什么办法可以让 sorted() 变得懒惰并在流式传输下一个元素之前再次应用于剩余元素?
任何其他关闭方法将不胜感激!!
我对你的理解是否正确,你想从列表中取出最大的数字,递减它,把它放回列表中,重复 10 次?
如果是,那么这是 PriorityQueue 的工作:
PriorityQueue<Integer> queue = Stream.of(2005,2020,2000,1967,2018)
.collect(toCollection(() -> new PriorityQueue(reverseOrder())));
Stream.generate(() -> {
Integer year = queue.poll();
queue.add(year - 1);
return year;
}).limit(10).forEach(System.out::println);
documentation of Stream.sorted()
说:
This is a stateful intermediate operation.
这又是described as
Stateful operations may need to process the entire input before producing a result. For example, one cannot produce any results from sorting a stream until one has seen all elements of the stream.
这说明了排序的非惰性性质,但是,这与您的问题无关。即使排序是惰性的,也没有改变流的基本原则,即每个项目被流式传输到终端操作最多一次。
您说您希望排序“懒惰”,但您实际期望的是在消费后对每个项目再次进行排序,这意味着对 n[=28 的流进行排序=] 元素意味着实际排序 n 项 n 次,这是其他人不会想到的,特别是因为 peek
并不意味着影响正在进行的操作的副作用。