简单合并用java FJ框架排序.....正确

时间:2014-01-10 21:31:12

标签: java sorting fork-join

我发布这个问题是因为我想向你们澄清在Java 1.7中使用F / J框架的概念,因为我看到互联网上的一些例子似乎没有意义。

使用List代替数组的代码是故意的。

这是递归合并排序的线性/常规版本。

package org.algorithms.sort;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


public class MergeSortor<T> {
    private final List<T> items;
    private final Comparator<T> c;

    public MergeSortor(final List<T> original, final Comparator<T> c) {
        if (original == null) {
            this.items = Collections.emptyList();
        } else {
            this.items = original;
        }
        this.c = c;
    }

    protected List<T> compute() {
        List<T> result = null;
        int currentSize = this.items.size();
        if (currentSize <= 1) {
            result = items;
        } else{
            int midPoint = currentSize / 2;
            List<T> left =new MergeSortor<T>(items.subList(0, midPoint), c).getSortedResult();
            List<T> right =new MergeSortor<T>(items.subList(midPoint,
                    currentSize), c).getSortedResult();
            result = merge(left,right);
        }
        return result;
    }
    private List<T> merge(List<T>left,List<T>right) {

        List<T> result = new ArrayList<T>(left.size()+right.size());
        T firstLeft = null;
        T firstRight = null;
        while (left.size() > 0 || right.size() > 0) {
            if (left.size() > 0 && right.size() > 0) {
                firstLeft = left.get(0);
                firstRight = right.get(0);
                if (c.compare(firstLeft, firstRight) <= 0) {
                    result.add(firstLeft);
                    left = left.subList(1, left.size());
                } else {
                    result.add(firstRight);
                    right = right.subList(1, right.size());
                }
            } else if (left.size() > 0){
                result.add(left.get(0));
                left = left.subList(1, left.size());
            } else if (right.size() > 0){
                result.add(right.get(0));
                right = right.subList(1, right.size());
            }
        }

        return result;
    }

    public List<T> getSortedResult() {
        return this.compute();
    }

    static public class IntegerComparator implements Comparator<Integer> {

        @Override
        public int compare(Integer o1, Integer o2) {
            int f = o1.hashCode(); // Auto-unboxing
            int s = o2.hashCode(); // Auto-unboxing
            return f < s ? -1 : (f == s ? 0 : 1); // No unboxing
        }
    }
}

这是扩展The RecursiveTask的合并排序的F / J版本。

package org.algorithms.sort;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.RecursiveTask;

public class MergeTask<T> extends RecursiveTask<List<T>>{
    private final List<T> items;
    private final Comparator<T> c;


    private static final long serialVersionUID = 8193108777395886772L;

    public MergeTask(final List<T> original, final Comparator<T> c){
        if (original == null) {
            this.items = Collections.emptyList();
        } else {
            this.items = original;
        }
        this.c = c;

    }

    @Override
    protected List<T> compute() {
        List<T> result = null;
        int currentSize = this.items.size();
        if (currentSize <= 1) {
            result = items;
        } else{
            int midPoint = currentSize / 2;
            MergeTask<T> leftSortor = new MergeTask<T>(items.subList(0, midPoint), c);
            MergeTask<T> rightSortor = new MergeTask<T>(items.subList(midPoint,
                    currentSize), c);

            rightSortor.fork(); 
            leftSortor.fork();
            result = merge(leftSortor.join(),rightSortor.join());
        }
        return result;
    }
    private List<T> merge(List<T>left,List<T>right) {

        List<T> result = new ArrayList<T>(left.size()+right.size());
        T firstLeft = null;
        T firstRight = null;
        while (left.size() > 0 || right.size() > 0) {
            if (left.size() > 0 && right.size() > 0) {
                firstLeft = left.get(0);
                firstRight = right.get(0);
                if (c.compare(firstLeft, firstRight) <= 0) {
                    result.add(firstLeft);
                    left = left.subList(1, left.size());
                } else {
                    result.add(firstRight);
                    right = right.subList(1, right.size());
                }
            } else if (left.size() > 0){
                result.add(left.get(0));
                left = left.subList(1, left.size());
            } else if (right.size() > 0){
                result.add(right.get(0));
                right = right.subList(1, right.size());
            }
        }

        return result;
    }

}

这是调用它们的主程序。

package org.algorithms.sort;

import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;

import org.algorithms.sort.MergeSortor.IntegerComparator;

    public class SortingRunner {

        public static void main(String[] args) throws InterruptedException, ExecutionException {
            Integer[] initialOrders = new Integer[Short.MAX_VALUE*32];
            Random random = new Random();
            for (int i =0 ;i<Short.MAX_VALUE*32;i++){
                initialOrders[i]=Integer.valueOf(random.nextInt(Integer.MAX_VALUE));
            }
            MergeSortor<Integer> sortor = new MergeSortor<Integer>(
                    Arrays.asList(initialOrders), new IntegerComparator());

            ForkJoinPool pool = new ForkJoinPool();
            MergeTask<Integer> task = new MergeTask<Integer>(Arrays.asList(initialOrders), new IntegerComparator());


            long start = System.currentTimeMillis();
            sortor.getSortedResult();
            long end =  System.currentTimeMillis();
            System.out.println(end - start );


            start = System.currentTimeMillis();
            pool.invoke(task);
            end =  System.currentTimeMillis();
            System.out.println(end - start );
        }

    }

我认为互联网上的问题是,大多数例子中的分叉是将分支任务的两条腿分开,或者先分叉左分叉部分然后向右分叉。

在使用F / J进行合并排序的情况下,我认为这应该是一个很大的不可以。

合并排序实际上是从左到右的线性依赖排序。首先分叉左边不会产生已经存在的任何进一步的并行过程。 F / J框架将fork()的所有内容按顺序提交到队列中,然后按提交顺序拾取并执行,由F / J池的每个工作线程分别执行。

然而,首先分叉将为您提供并行计算以后应该执行的内容(与原始/线性实现相比)的优势,并首先对尾部进行除法/合并。

让我知道你们的想法。并希望这将是使用F / J进行排序的一个很好的例子。

0 个答案:

没有答案