简体   繁体   English

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

[英]How to write sorting and grouping algorithm shorter?

I have written a sorting algorithm but in an ugly way and I am wondering if someone would help me how to improve it (make code shorter)? 我已经写了一个排序算法,但是方法很丑陋,我想知道是否有人会帮助我改进它(使代码更短)? I am limited to use Java 6. 我仅限使用Java 6。

  1. Group elements in multimap 多图中的组元素
  2. Sort Elements in Groups (by date asc). 按组对元素排序(按日期升序)。 Put sorted groups into list of lists. 将已排序的组放入列表列表。
  3. Sort list by date asc of the first element in the group. 按组中第一个元素的日期升序对列表进行排序。
  4. Flatten the list of list to a list of elements. 将列表列表展平为元素列表。

The sorting is implemented in the sort method. 排序是通过sort方法实现的。

Input List: 32102421 <-sorted by this values ascending 11231455 <-grouped by this values 输入列表:32102421 <-按此值排序升序11231455 <-按此值分组

Output List: 01122234 32551114 输出列表: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;
    }

}

Rather than reinventing the wheel, and since you are using Guava, use a TreeMultimap since in this Multimap implementation, "keys and values are ordered by their natural ordering or by supplied comparators." 由于使用了Guava,因此TreeMultimap重新设计轮子,而是使用TreeMultimap因为在此Multimap实现中,“键和值通过其自然顺序或提供的比较器进行排序”。

You create one using static factory methods; 您使用静态工厂方法创建一个。 for instance, this one . 例如, 这个

However : please note that it implements SetMultimap , as such you cannot have duplicate elements in values. 但是 :请注意,它实现SetMultimap ,因此您不能在值中包含重复的元素。

What I would do is to first iterate on the data to retrieve the minimum date for each pio , then just sort using Collections.sort() based on the pio , and if the pio are the same, on the date : 我会做的是对数据的第一循环以检索每个最小日期pio ,那么就使用排序Collections.sort()基础上, pio ,如果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;
}

Output on the test data: 输出测试数据:

[[0:3], [1:2], [1:5], [2:5], [2:1], [2:1], [3:1], [4:4]]

EDIT: As suggested by Olivier Grégoire, you can also use Guava's ComparisonChain in the Comparator for more compact code: 编辑:作为由Olivier格雷的建议,你也可以用番石榴的ComparisonChainComparator了更紧凑的代码:

    Collections.sort(sortedData, new Comparator<ElementToSort>() {
        @Override
        public int compare(ElementToSort voy1, ElementToSort voy2) {
            return ComparisonChain.start()
                .compare(minDates.get(voy1.getPio()), minDates.get(voy2.getPio()))
                .compare(voy1.getPio(), voy2.getPio())
                .compare(voy1.getDate(), voy2.getDate())
                .result();
        }
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM