对java集合进行排序和分组
我有一个有名字和分数的物体。我想对这些对象的集合进行排序,以便它们按名称分组,并按每组中的最大分数排序(在组内也按分数递减排序) 让我展示一下我打算实现的目标。假设我有这些对象(名称、分数): (a,3)对java集合进行排序和分组,java,Java,我有一个有名字和分数的物体。我想对这些对象的集合进行排序,以便它们按名称分组,并按每组中的最大分数排序(在组内也按分数递减排序) 让我展示一下我打算实现的目标。假设我有这些对象(名称、分数): (a,3) (a,9) (b,7) (b,10) (c,8) (c,3) 然后我希望它们按如下方式分类: (b,10) (b,7) (a,9) (a,3) (c,8) (c,3) 使用比较器是否可行?我想不出来,所以任何提示都将不胜感激。是的 在比较中首先优先选择名称,然后评分。它也将与排序的分数一起分组
(a,9)
(b,7)
(b,10)
(c,8)
(c,3) 然后我希望它们按如下方式分类: (b,10)
(b,7)
(a,9)
(a,3)
(c,8)
(c,3) 使用比较器是否可行?我想不出来,所以任何提示都将不胜感激。是的 在比较中首先优先选择
名称
,然后评分。它也将与排序的分数一起分组
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);
List scores=new ArrayList();
分数。添加(新分数(“a”,58));
分数。添加(新分数(“a”,10));
分数。添加(新分数(“b”,165));
分数。添加(新分数(“a”,1));
分数。添加(新分数(“b”,1658));
分数。添加(新分数(“c”,1));
分数。添加(新分数(“c”,10));
分数。添加(新分数(“c”,0));
Collections.sort(分数,新比较器(){
公共整数比较(分数o1,分数o2){
如果(o1.getName().compareTo(o2.getName())==0){
返回o2.getScore()-o1.getScore();
}否则{
返回o1.getName().compareTo(o2.getName());
}
}
});
系统输出打印项次(分数);
更新
正如克里斯指出的那样
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);
}
}
import java.util.*;
/**
*
*@作者Jigar
*/
班级成绩{
私有字符串名称;
私人名单分数;
公众分数(){
}
公共分数(字符串名称、列表分数){
this.name=名称;
这个分数=分数;
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共列表getScores(){
返回分数;
}
公开考试分数(列出分数){
这个分数=分数;
}
@凌驾
公共字符串toString(){
返回名称+“,“+分数+”\n”;
}
}
公共类{
公共静态void main(字符串[]args){
列表分数=新的ArrayList();
List lstA=new ArrayList();
lstA.添加(3);
lstA.添加(9);
lstA.添加(7);
集合排序(lstA);
收藏。反向(lstA);
List lstB=new ArrayList();
lstB.添加(10);
lstB.添加(8);
lstB.添加(3);
集合。排序(lstB);
收藏。反向(lstB);
List lstC=new ArrayList();
lstC.添加(8);
lstC.添加(3);
集合。排序(lstC);
收藏。反向(lstC);
分数。添加(新分数(“a”,lstA));
分数。添加(新分数(“b”,lstB));
分数。添加(新分数(“c”,lstC));
Collections.sort(分数,新比较器(){
公共整数比较(分数o1,分数o2){
返回o2.getScores().get(0).compareTo(o1.getScores().get(0));
}
});
系统输出打印项次(分数);
}
}
比较器进行单一排序
你必须:
按名称分组
按组中的最高分数对组进行排序
然后,您需要将组展平回到列表中
使用Java8
编辑:自从我写了这个答案后,Java 8就问世了,这大大简化了问题:
import java.util.*;
import static java.util.Comparator.*;
import static java.util.stream.Collectors.*;
其中,记录被分组为排序的TreeSet
s,而不是作为流的第一个操作对值进行排序,然后按其第一个最高值对集合进行排序
如果组较大,则在排序之前进行分组是合适的,以减少冗余比较
实施可比的
:
通过让您的记录实现可比性
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());
*/
}
...
}
公共类记录实现可比较{
@凌驾
公共整数比较(记录其他){
//最高优先
return-Integer.compare(getScore(),other.getScore());
/*或相当于:
返回整数.compare(other.getScore(),getScore());
*/
}
...
}
List result=records.stream()
.collect(groupingBy(记录::getName,toCollection(树集::新建)))
.values().stream()
.sorted(比较(SortedSet::first))
.flatMap(集合::流)
.collect(toList());
Java 8之前 编辑:这里是一个非常粗略的单元测试,演示了一种方法。我还没有把它清理干净 像这样的东西在Java中是痛苦的,我通常会使用它
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);
}
}
}
import org.junit.Test;
导入java.util.*;
导入静态java.util.Arrays.asList;
导入静态org.junit.Assert.assertEquals;
公共类GroupSortTest{
@试验
公共void testGroupSort(){
列表记录=asList(
新纪录(a,3),,
新纪录(a,9),,
新纪录(b,7),,
新纪录(b,10),,
新纪录(c,8),,
新纪录("c,3);;
列表记录GroupedByName=GroupRecordsByName和SortedByCoreDescending(记录);
排序(recordsGroupedByName,byHighestScoreInGroupDescending());
列表结果=组(recordsGroupedByName);
预期列表=asList(
新纪录(b,10),,
新纪录(b,7),,
新纪录(a,9),,
新纪录(a,3),,
新纪录(c,8),,
新纪录("c,3);;
资产质量(预期、结果);
}
专用列表组(列表记录组){
列表结果=新建ArrayList();
用于(分类地图组:记录组){
result.addAll(group.values());
}
返回r
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());
*/
}
...
}
List<Record> result = records.stream()
.collect(groupingBy(Record::getName, toCollection(TreeSet::new)))
.values().stream()
.sorted(comparing(SortedSet::first))
.flatMap(Collection::stream)
.collect(toList());
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);
}
}
}
class Item{
String name;
int score;
}
new Comparator<Item>(){
@Override
public int compare(Item o1, Item o2) {
if (o1.name.equals(o2.name)) {
return o1.score > o2.score ? 1 : -1; // might have to flip this. I didn't test
}else {
return o1.name.compareTo(o2.name);
}
}
};
public class SortThings {
static class Thing {
public final String name;
public final int score;
public Thing(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "(" + name + ", " + score + ")";
}
}
public static void main(String[] args) {
Collection<Thing> things = Arrays.asList(
new Thing("a", 3),
new Thing("a", 9),
new Thing("b", 7),
new Thing("b", 10),
new Thing("c", 8),
new Thing("c", 3)
);
SortedSet<SortedSet<Thing>> sortedGroups = sortThings(things);
System.out.println(sortedGroups);
}
private static SortedSet<SortedSet<Thing>> sortThings(Collection<Thing> things) {
final Comparator<Thing> compareThings = new Comparator<Thing>() {
public int compare(Thing a, Thing b) {
Integer aScore = a.score;
Integer bScore = b.score;
return aScore.compareTo(bScore);
}
};
// first pass
Map<String, SortedSet<Thing>> groups = new HashMap<String, SortedSet<Thing>>();
for (Thing obj: things) {
SortedSet<Thing> group = groups.get(obj.name);
if (group == null) {
group = new TreeSet<Thing>(compareThings);
groups.put(obj.name, group);
}
group.add(obj);
}
// second pass
SortedSet<SortedSet<Thing>> sortedGroups = new TreeSet<SortedSet<Thing>>(new Comparator<SortedSet<Thing>>() {
public int compare(SortedSet<Thing> a, SortedSet<Thing> b) {
return compareThings.compare(a.last(), b.last());
}
});
sortedGroups.addAll(groups.values());
return sortedGroups;
}
}
public class ScoreComparator implements Comparator<Item>
{
public int compare(Item a, Item b){
if (a.name.equals(b.name){
return a.score.compareTo(b.score);
}
return a.name.compareTo(b.Name);
}
}