我有一个有名字和分数的对象.我想对这些对象的集合进行排序,以便按名称对它们进行分组,并按每组中的最高分数进行排序(并且在组内也按降序分数排序).
让我展示一下我打算实现的目标.假设我有这些对象(名称,分数):
(a,3)
(a,9)
(b,7)
(b,10)
(c,8)
(c,3)
然后我希望他们像这样排序:
(b,10)
(b,7)
(a,9)
(a,3)
(c,8)
(c,3)
这对比较器来说是可行的吗?我无法弄明白,所以任何提示都会受到赞赏.
Chr*_*röm 22
不,你不能用单一的单一种类做到这一点Comparator.
你必须按名称,并在组群,由最高得分进行排序.
然后,您需要将组展平回列表.
编辑:因为我写了这个答案,Java 8已经问世,这简化了很多问题:
import java.util.*;
import static java.util.Comparator.*;
import static java.util.stream.Collectors.*;
Run Code Online (Sandbox Code Playgroud)
List<Record> result = records.stream()
.sorted(comparingInt(Record::getScore).reversed())
.collect(groupingBy(Record::getName, LinkedHashMap::new, toList()))
.values().stream()
.flatMap(Collection::stream)
.collect(toList());
Run Code Online (Sandbox Code Playgroud)
首先我们按分数排序,然后我们使用a进行分组LinkedHashMap,这将保留键的插入顺序,因此具有较高分数的键将首先出现.
如果组很小,则首先排序是正常的,因此不同组中的对象之间的冗余比较不会造成太大影响.
此外,使用此方法,将保留重复项.
或者,如果您不关心保留重复项,您可以:
Comparator<Record> highestScoreFirst = comparingInt(Record::getScore).reversed();
List<Record> result = records.stream()
.collect(groupingBy(Record::getName,
toCollection(() -> new TreeSet<>(highestScoreFirst))))
.values().stream()
.sorted(comparing(SortedSet::first, highestScoreFirst))
.flatMap(Collection::stream)
.collect(toList());
Run Code Online (Sandbox Code Playgroud)
将记录分组为已排序的TreeSets,而不是将值排序为流的第一个操作,然后按照第一个最高值对这些集进行排序.
如果组很大,则在排序之前进行分组是合适的,以减少冗余比较.
Comparable:你可以通过制作记录来缩短它 Comparable
public class Record implements Comparable<Record> {
@Override
public int compareTo(Record other) {
// Highest first
return -Integer.compare(getScore(), other.getScore());
/* Or equivalently:
return Integer.compare(other.getScore(), getScore());
*/
}
...
}
Run Code Online (Sandbox Code Playgroud)
List<Record> result = records.stream()
.collect(groupingBy(Record::getName, toCollection(TreeSet::new)))
.values().stream()
.sorted(comparing(SortedSet::first))
.flatMap(Collection::stream)
.collect(toList());
Run Code Online (Sandbox Code Playgroud)
编辑:这是一个非常粗略的单元测试,演示了一种方法.我没有像我希望的那样清理它.
这样的东西在Java中是痛苦的,我通常会使用Google Guava.
import org.junit.Test;
import java.util.*;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
public class GroupSortTest {
@Test
public void testGroupSort() {
List<Record> records = asList(
new Record("a", 3),
new Record("a", 9),
new Record("b", 7),
new Record("b", 10),
new Record("c", 8),
new Record("c", 3));
List<SortedMap<Integer, Record>> recordsGroupedByName = groupRecordsByNameAndSortedByScoreDescending(records);
Collections.sort(recordsGroupedByName, byHighestScoreInGroupDescending());
List<Record> result = flattenGroups(recordsGroupedByName);
List<Record> expected = asList(
new Record("b", 10),
new Record("b", 7),
new Record("a", 9),
new Record("a", 3),
new Record("c", 8),
new Record("c", 3));
assertEquals(expected, result);
}
private List<Record> flattenGroups(List<SortedMap<Integer, Record>> recordGroups) {
List<Record> result = new ArrayList<Record>();
for (SortedMap<Integer, Record> group : recordGroups) {
result.addAll(group.values());
}
return result;
}
private List<SortedMap<Integer, Record>> groupRecordsByNameAndSortedByScoreDescending(List<Record> records) {
Map<String, SortedMap<Integer, Record>> groupsByName = new HashMap<String, SortedMap<Integer, Record>>();
for (Record record : records) {
SortedMap<Integer, Record> group = groupsByName.get(record.getName());
if (null == group) {
group = new TreeMap<Integer, Record>(descending());
groupsByName.put(record.getName(), group);
}
group.put(record.getScore(), record);
}
return new ArrayList<SortedMap<Integer, Record>>(groupsByName.values());
}
private DescendingSortComparator descending() {
return new DescendingSortComparator();
}
private ByFirstKeyDescending byHighestScoreInGroupDescending() {
return new ByFirstKeyDescending();
}
private static class ByFirstKeyDescending implements Comparator<SortedMap<Integer, Record>> {
public int compare(SortedMap<Integer, Record> o1, SortedMap<Integer, Record> o2) {
return o2.firstKey().compareTo(o1.firstKey());
}
}
private static class DescendingSortComparator implements Comparator<Comparable> {
public int compare(Comparable o1, Comparable o2) {
return o2.compareTo(o1);
}
}
}
Run Code Online (Sandbox Code Playgroud)
是的 去吧Comparator
先比较name,再评分。它也将与排序分数分组
List<Score> scores = new ArrayList<Score>();
scores.add(new Score("a", 58));
scores.add(new Score("a", 10));
scores.add(new Score("b", 165));
scores.add(new Score("a", 1));
scores.add(new Score("b", 1658));
scores.add(new Score("c", 1));
scores.add(new Score("c", 10));
scores.add(new Score("c", 0));
Collections.sort(scores, new Comparator<Score>() {
public int compare(Score o1, Score o2) {
if (o1.getName().compareTo(o2.getName()) == 0) {
return o2.getScore() - o1.getScore();
} else {
return o1.getName().compareTo(o2.getName());
}
}
});
System.out.println(scores);
Run Code Online (Sandbox Code Playgroud)
正如克里斯指出的那样。
import java.util.*;
/**
*
* @author Jigar
*/
class Score {
private String name;
private List<Integer> scores;
public Score() {
}
public Score(String name, List<Integer> scores) {
this.name = name;
this.scores = scores;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Integer> getScores() {
return scores;
}
public void setScores(List<Integer> scores) {
this.scores = scores;
}
@Override
public String toString() {
return name + " , " + scores + "\n";
}
}
public class ScoreDemo {
public static void main(String[] args) {
List<Score> scores = new ArrayList<Score>();
List<Integer> lstA = new ArrayList<Integer>();
lstA.add(3);
lstA.add(9);
lstA.add(7);
Collections.sort(lstA);
Collections.reverse(lstA);
List<Integer> lstB = new ArrayList<Integer>();
lstB.add(10);
lstB.add(8);
lstB.add(3);
Collections.sort(lstB);
Collections.reverse(lstB);
List<Integer> lstC = new ArrayList<Integer>();
lstC.add(8);
lstC.add(3);
Collections.sort(lstC);
Collections.reverse(lstC);
scores.add(new Score("a", lstA));
scores.add(new Score("b", lstB));
scores.add(new Score("c", lstC));
Collections.sort(scores, new Comparator<Score>() {
public int compare(Score o1, Score o2) {
return o2.getScores().get(0).compareTo(o1.getScores().get(0));
}
});
System.out.println(scores);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25616 次 |
| 最近记录: |