Java8并行流按给定值重新组织列表

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>();

若元素小于给定值,则向左移动,若元素大于给定值,则向右移动。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>();
    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(右)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