如何编写排序和分组算法更短?

时间:2014-11-04 09:37:36

标签: java algorithm sorting guava java-6

我已经写了一个排序算法,但是很难看,我想知道是否有人会帮助我如何改进它(使代码缩短)?我只能使用Java 6。

  1. 多地图中的组元素
  2. 对组中的元素进行排序(按日期asc)。将已排序的组放入列表列表中。
  3. 按组中第一个元素的日期asc排序列表。
  4. 将列表列表展平为元素列表。
  5. 排序是在排序方法中实现的。

    输入清单: 32102421< -sorted by this values ascending 11231455< -grouped by this values

    输出清单: 01122234 32551114

        public static void main(String[] args) {
        System.out.println(sort(prepareTestData1()));
    }
    
    public static List<ElementToSort> sort(List<ElementToSort> testData) {
        ListMultimap<Integer, ElementToSort> voyagesMap = LinkedListMultimap.create();
        // 1. Group elements in multimap
        for (ElementToSort voyage : testData) {
            voyagesMap.put(voyage.getPio(), voyage);
        }
    
        // 2. Sort Elements in Groups (by date asc). Put sorted groups into list of lists.
        List<List<ElementToSort>> preSortedList = new ArrayList<List<ElementToSort>>();
        for (Integer key : voyagesMap.keySet()) {
            List<ElementToSort> voyages = voyagesMap.get(key);
            preSortedList.add(Ordering.from(getDateComparator()).sortedCopy(voyages));
        }
    
        // 3. Sort list by date asc of the first element in the group.
        preSortedList = Ordering.from(getDateListComparator()).sortedCopy(preSortedList);
    
        // 4. Flatten the list of list to a list of elements.
        List<ElementToSort> returnList = new ArrayList<ElementToSort>();
        for (List<ElementToSort> packOfVoyages : preSortedList) {
            returnList.addAll(packOfVoyages);
        }
    
        return returnList;
    }
    
    public static List<ElementToSort> prepareTestData1() {
        return Arrays.asList(new ElementToSort(3, 1), new ElementToSort(2, 1), new ElementToSort(1, 2), new ElementToSort(0, 3), new ElementToSort(2, 1), new ElementToSort(4, 4), new ElementToSort(2, 5), new ElementToSort(1, 5));
    }
    
    public static Comparator<ElementToSort> getDateComparator() {
    
        return new Comparator<ElementToSort>() {
    
            @Override
            public int compare(ElementToSort voy1, ElementToSort voy2) {
                if (voy1.getDate() < voy2.getDate()) {
                    return -1;
                } else if (voy1.getDate() > voy2.getDate()) {
                    return 1;
                } else {
                    return 0;
                }
            }
        };
    }
    
    public static Comparator<List<ElementToSort>> getDateListComparator() {
    
        return new Comparator<List<ElementToSort>>() {
    
            @Override
            public int compare(List<ElementToSort> voy1, List<ElementToSort> voy2) {
                if (voy1.get(0).getDate() < voy2.get(0).getDate()) {
                    return -1;
                } else if (voy1.get(0).getDate() > voy2.get(0).getDate()) {
                    return 1;
                } else {
                    return 0;
                }
            }
        };
    }
    
    public static class ElementToSort {
        int date;
        int pio;
    
        @Override
        public String toString() {
            return "[" + date + ":" + pio + "]";
        }
    
        public ElementToSort(int date, int pio) {
            super();
            this.date = date;
            this.pio = pio;
        }
    
        public int getDate() {
            return date;
        }
    
        public void setDate(int date) {
            this.date = date;
        }
    
        public int getPio() {
            return pio;
        }
    
        public void setPio(int pio) {
            this.pio = pio;
        }
    
    }
    

2 个答案:

答案 0 :(得分:4)

不是重新发明轮子,而是因为你正在使用Guava,所以使用TreeMultimap,因为在Multimap实现中,&#34;键和值按其自然顺序或提供的比较器排序&#34;

使用静态工厂方法创建一个;例如,this one

但是:请注意它实现了SetMultimap,因此您不能在值中包含重复的元素。

答案 1 :(得分:1)

我要做的是首先迭代数据以检索每个pio的最小日期,然后根据Collections.sort()使用pio进行排序,如果是{{} 1}}在pio

上是相同的
date

测试数据的输出:

public static List<ElementToSort> sort(final List<ElementToSort> testData) {
    // minimum date associated to each pio
    final Map<Integer, Integer> minDates = new HashMap<Integer, Integer>();

    for (final ElementToSort voy : testData) {
        if (!minDates.containsKey(voy.getPio()) || minDates.get(voy.getPio()) > voy.getDate()) {
            minDates.put(voy.getPio(), voy.getDate());
        }
    }

    // copy testData in case it's read-only
    final List<ElementToSort> sortedData = new ArrayList<ElementToSort>(testData);

    Collections.sort(sortedData, new Comparator<ElementToSort>() {
        @Override
        public int compare(ElementToSort voy1, ElementToSort voy2) {
            int cmp = minDates.get(voy1.getPio()) - minDates.get(voy2.getPio());
            // just in case we have different pio with the same date
            if (cmp == 0) {
                cmp = voy1.getPio() - voy2.getPio();
            }
            if (cmp == 0) {
                cmp = voy1.getDate() - voy2.getDate();
            }
            return cmp;
        }
    });

    return sortedData;
}

编辑:正如OlivierGrégoire所建议的那样,您也可以在[[0:3], [1:2], [1:5], [2:5], [2:1], [2:1], [3:1], [4:4]] 中使用Guava的ComparisonChain来获得更紧凑的代码:

Comparator