[英]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。
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格雷的建议,你也可以用番石榴的ComparisonChain
在Comparator
了更紧凑的代码:
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.