Java8并行流按给定值重新组织列表
若元素小于给定值,则向左移动,若元素大于给定值,则向右移动。java 7风格的简单代码:Java8并行流按给定值重新组织列表,java,parallel-processing,java-8,java-stream,Java,Parallel Processing,Java 8,Java Stream,若元素小于给定值,则向左移动,若元素大于给定值,则向右移动。java 7风格的简单代码: private static <T extends Comparable> List<T> doAction(List<T> original, T state) { List<T> left = new ArrayList<T>(); List<T> fight = new ArrayList<T>();
private static <T extends Comparable> List<T> doAction(List<T> original, T state) {
List<T> left = new ArrayList<T>();
List<T> fight = new ArrayList<T>();
for (T e : original) {
if (e.compareTo(state) < 0) {
left.add(e);
} else {
fight.add(e);
}
}
left.addAll(fight);
return left;
}
私有静态列表doAction(列表原始,T状态){
左列表=新建ArrayList();
List-fight=new-ArrayList();
适用于(T e:原件){
如果(例如,与(状态)相比<0){
左.加入(e);
}否则{
加入(e);
}
}
左。addAll(战斗);
左转;
}
如何使用并行流将上述代码重写为java 8流样式?与原始代码等效的一种方法是:
private static <T extends Comparable<T>> List<T> doAction(List<T> original, T state) {
Map<Boolean, List<T>> collect = original.parallelStream()
.collect(Collectors.partitioningBy(e -> e.compareTo(state) < 0));
List<T> left = collect.get(true);
List<T> right = collect.get(false);
return Stream.of(left, right).flatMap(List::stream).collect(Collectors.toList());
}
private static <T extends Comparable<T>> List<T> doAction(List<T> original, T state) {
return original.parallelStream()
.sorted(Comparator.comparingInt(e -> Integer.signum(e.compareTo(state))|1))
.collect(Collectors.toList());
}
与原始代码等效的一种方法是:
private static <T extends Comparable<T>> List<T> doAction(List<T> original, T state) {
Map<Boolean, List<T>> collect = original.parallelStream()
.collect(Collectors.partitioningBy(e -> e.compareTo(state) < 0));
List<T> left = collect.get(true);
List<T> right = collect.get(false);
return Stream.of(left, right).flatMap(List::stream).collect(Collectors.toList());
}
private static <T extends Comparable<T>> List<T> doAction(List<T> original, T state) {
return original.parallelStream()
.sorted(Comparator.comparingInt(e -> Integer.signum(e.compareTo(state))|1))
.collect(Collectors.toList());
}
尽管霍尔格的答案很好,但您(或其他读者)可能对编写自己的
收集器
感兴趣,或者想知道如何编写一个
首先,您需要一种表示部分结果的方法
static class PartialResult<T extends Comparable<T>> {
public List<T> left = new ArrayList<>();
public List<T> right = new ArrayList<>();
}
供应商
很简单,我们只需要告诉它创建一个新实例累加器
,给定一个元素,我们将它相应地放在它的部分中combiner
,我们有两个部分结果(多线程计算了解决方案树的两个分支),将它们合并为一个finsiher
,最后,我想要一个完整的列表,而不是部分解决方案李>
尽管霍尔格的答案很好,但您(或其他读者)可能对编写自己的
收集器
感兴趣,或者想知道如何编写一个
首先,您需要一种表示部分结果的方法
static class PartialResult<T extends Comparable<T>> {
public List<T> left = new ArrayList<>();
public List<T> right = new ArrayList<>();
}
供应商
很简单,我们只需要告诉它创建一个新实例累加器
,给定一个元素,我们将它相应地放在它的部分中combiner
,我们有两个部分结果(多线程计算了解决方案树的两个分支),将它们合并为一个finsiher
,最后,我想要一个完整的列表,而不是部分解决方案李>
为什么你认为平行流会对你的情况有所帮助?你有这样一个大的列表来排序吗?并不是每个问题都适合并行化;这可能是其中之一。@Nicolas Filotto:一个有序的并行流将保持遭遇顺序,即使处理顺序不同,请参阅@Holger Interest thx以获取共享为什么您认为并行流对您的情况有帮助?你有这样一个大的列表来排序吗?并不是每个问题都适合并行化;这可能是其中之一。@Nicolas Filotto:一个有序的并行流将保持遭遇顺序,即使处理顺序不同,请参阅@Holger Interest thx for Sharing创建一个包含两个列表的新流以构建单个列表是否真的有帮助?为什么不干脆向左。addAll(右);向左返回@Nicolas Filotto:因为
left
不能保证是可变列表。在当前的实现中,它是一个ArrayList
,但这可能会改变。您必须使用更复杂的收集器Collectors.partitioning by(…,Collectors.toCollection(ArrayList::new))
以确保可以在结果列表上调用addAll
。但是,除非您有一个非常小的右侧
列表,否则左侧
的容量不太可能足以满足后续的添加所有
,因此在引擎盖下执行的复制操作的数量不会改变。因此我保持了收集器的简单性;左。addAll(右)代码>或者,如果性能很重要,result=newarraylist(left.size()+right.size());结果:addAll(左);结果:addAll(右)正如前面所说,我只是想让它保持简单。无论如何,我更喜欢第二种方法。是的,第二种方法确实更好,因为我们知道结果列表的大小,所以它会更快,我知道以后我们可以得到一个不可变列表,但我的观点只是避免过度使用流,即使是对于附加两个列表这样的琐碎操作。“如果你只有一把锤子,一切看起来都像钉子。”:-)创建一个包含两个列表的新流来构建一个列表真的有帮助吗?为什么不干脆向左。addAll(右);向左返回@Nicolas Filotto:因为left
不能保证是可变列表。在当前的实现中,它是一个ArrayList
,但这可能会改变。您必须使用更复杂的收集器Collectors.partitioning by(…,Collectors.toCollection(ArrayList::new))
以确保可以在结果列表上调用addAll
。但是,除非您有一个非常小的右侧
列表,否则左侧
的容量不太可能足以满足后续的添加所有
,因此在引擎盖下执行的复制操作的数量不会改变。因此我保持了收集器的简单性;左。addAll(右)代码>或者,如果性能很重要,result=newarraylist(left.size()+right.size());结果:addAll(左);结果:addAll(右)正如前面所说,我只是想让它保持简单。无论如何,我更喜欢第二种方法。是的,第二种方法确实更好,因为我们知道结果列表的大小,所以它会更快,我知道以后我们可以得到一个不可变列表,但我的观点只是避免过度使用流,即使是对于附加两个列表这样的琐碎操作。“如果你只有一把锤子,一切看起来都像钉子。”:-)请注意,组合器可以修改它的一个参数并返回该参数,因此,不必创建新的ResultPair
,只需执行(r1,r2)->{r1.left.addAll(r2.left);r1.right.addAll(r2.right);返回r1;}
。此外,累加器可以简化为(result,e)->(e.compareTo(pivot))注意,允许组合器修改其一个参数并返回该参数,因此您可以简单地执行以下操作,而不是创建新的ResultPair