Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Java流从ArrayList获得最高分数_Java_Lambda_Java 8_Java Stream_Comparator - Fatal编程技术网

使用Java流从ArrayList获得最高分数

使用Java流从ArrayList获得最高分数,java,lambda,java-8,java-stream,comparator,Java,Lambda,Java 8,Java Stream,Comparator,我希望通过Id获得最高分数组。如果两个最高分数相同,那么我希望根据最低可选Id获得最高分数。我希望在Java流中获得它。到目前为止,我正在尝试以下代码,但这些代码不起作用 例如: 数组列表: ID:1得分:80可选ID:1 ID:1得分:90可选ID:2 ID:1得分:90可选ID:3 ID:2得分:80可选ID:1 ID:2分数:100可选ID:3 ID:2分数:100可选ID:5 结果应该是 ID:1分90可选ID:2 ID 2得分100可选ID:3 Map<Long, Optiona

我希望通过Id获得最高分数组。如果两个最高分数相同,那么我希望根据最低可选Id获得最高分数。我希望在Java流中获得它。到目前为止,我正在尝试以下代码,但这些代码不起作用 例如:

数组列表:

ID:1得分:80可选ID:1
ID:1得分:90可选ID:2
ID:1得分:90可选ID:3
ID:2得分:80可选ID:1
ID:2分数:100可选ID:3
ID:2分数:100可选ID:5

结果应该是

ID:1分90可选ID:2
ID 2得分100可选ID:3

Map<Long, Optional<Person>> result1 = records.stream()
                  .collect(Collectors.groupingBy(Person::getId,
                          Collectors.maxBy(Comparator.comparing(Person::getScore)),
                          Collector.minBy(Comparator.comparing(Person::getOptionalId))));


        for(Person ns: result1) {

            sb.append(ns.getBatchNumber());
            sb.append(',');
Map result1=records.stream()
.collect(收集器).groupingBy(Person::getId,
Collectors.maxBy(Comparator.comparing(Person::getScore)),
Collector.minBy(Comparator.comparing(Person::getOptionalId));
对于(人员ns:result1){
sb.append(ns.getBatchNumber());
某人附加(“,”);

我做了一些修改,引入了一个比较score和optionId的helper类

public class T21Group {

public static void main(String[] args) {
    List<Person> records = new ArrayList<>();
    records.add(new Person(1, 80, 1));
    records.add(new Person(1, 90, 2));
    records.add(new Person(1, 90, 3));
    records.add(new Person(2, 80, 1));
    records.add(new Person(2, 100, 3));
    records.add(new Person(2, 100, 5));

    Map<Long, Optional<Person>> result1 = records.stream()
            .collect(Collectors.groupingBy(Person::getId, Collectors.maxBy(Comparator.comparing(Pair::new))));

    for (Optional<Person> ns : result1.values()) {
        System.out.println(ns);
    }
}

public static class Pair implements Comparable<Pair> {
    long score;
    long optionalId;

    public Pair(Person p) {
        score = p.getScore();
        optionalId = p.getOptionalId();
    }

    @Override
    public int compareTo(Pair o) {
        if (this.score == o.score) {
            return Long.compare(o.optionalId, this.optionalId);
        }
        return Long.compare(this.score, o.score);
    }

}

public static class Person {
    private long id;
    private long score;
    private long optionalId;

    public Person(long id, long score, long optionalId) {
        this.id = id;
        this.score = score;
        this.optionalId = optionalId;
    }

    @Override
    public String toString() {
        return "ID: " + id + " Score: " + score + " OptionalId: " + optionalId;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public long getScore() {
        return score;
    }

    public void setScore(long score) {
        this.score = score;
    }

    public long getOptionalId() {
        return optionalId;
    }

    public void setOptionalId(long optionalId) {
        this.optionalId = optionalId;
    }

}

}
公共类T21组{
公共静态void main(字符串[]args){
列表记录=新的ArrayList();
记录。添加(新人员(1,80,1));
记录。添加(新人员(1、90、2));
记录。添加(新人员(1、90、3));
记录。添加(新人员(2,80,1));
记录。添加(新人员(2100,3));
记录。添加(新人员(2100,5));
Map result1=records.stream()
.collect(Collectors.groupingBy(Person::getId,Collectors.maxBy(Comparator.comparing(Pair::new)));
for(可选ns:result1.values()){
系统输出打印项次(ns);
}
}
公共静态类对实现了可比较的{
长分数;
长期权;
公共对(p人){
分数=p.getScore();
optionalId=p.getOptionalId();
}
@凌驾
公共整数比较(o对){
如果(this.score==o.score){
返回Long.compare(o.optionId,this.optionId);
}
返回长。比较(this.score,o.score);
}
}
公共静态类人员{
私人长id;
私人长分数;
私人长期期权;
公众人物(长id、长分数、长可选id){
this.id=id;
这个分数=分数;
this.optionald=optionald;
}
@凌驾
公共字符串toString(){
返回“ID:+ID+”分数:“+Score+”选项ID:“+OptionalId”;
}
公共长getId(){
返回id;
}
公共无效集合id(长id){
this.id=id;
}
公共长getScore(){
返回分数;
}
公共核心(长分数){
这个分数=分数;
}
公共长getoptionId(){
返回期权;
}
公共无效设置选项ID(长选项ID){
this.optionald=optionald;
}
}
}

您可以尝试以下流代码,该流代码按
ID
聚合,然后使用两级排序查找最大分数,首先按分数排序,然后在分数平分的情况下按可选ID排序:

import static java.util.Collections.reverseOrder;
import static java.util.Comparator.comparing;

Map<Long, Optional<Person>> result1 = records.stream()
    .collect(Collectors.groupingBy(Person::getId,
             Collectors.maxBy(
                 Comparator.comparing(Person::getScore)
                  .thenComparing(reverseOrder(comparing(Person::getOptionalId))))));

Optional[ID: 1 Score: 90 OptionalId: 2]
Optional[ID: 2 Score: 100 OptionalId: 3]
导入静态java.util.Collections.reverseOrder;
导入静态java.util.Comparator.Comparating;
Map result1=records.stream()
.collect(收集器).groupingBy(Person::getId,
麦克斯比(
比较者。比较(Person::getScore)
.然后比较(反向顺序(比较(Person::getOptionalId()()())));
可选[ID:1分数:90可选ID:2]
可选[ID:2分数:100可选ID:3]
这里的技巧是只反转可选ID的排序顺序,我们希望它是升序,而不是降序。默认情况下,排序顺序是降序,因为我们调用的是
Collections.maxBy

我引用了反向语法的帮助。另外,我从@mayamar借用了锅炉板代码来设置以下演示:


(演示仅用于演示)

我建议您从自定义开始,将最大
得分
作为优先级,然后将最小值
作为可选ID
。为了简洁起见,最好将其传递给变量:

final Comparator<Person> comparator = Comparator
    .comparing(Person::getScore)                 // descending score first
    .thenComparing(Comparator                    // then ..
        .comparing(Person::getOptionalId)        // .. optionalId
        .reversed());                            // .. but ascending
[个人[id=1,分数=90,可选id=2],个人[id=2,分数=100,可选id=3]]


对于给定的Id值,必须有个人。Id值的存在完全取决于个人。因此,如果存在Id,也必须有个人。因此,将
可选
作为映射的值有什么意义。相比之下,仅将
个人
实例作为中的值更有意义de>map。在这里,我使用
toMap
收集器和
BinaryOperator.maxBy
来完成工作。下面是它的外观。请注意
BinaryOperator.maxBy
是如何用作
合并函数的

Map<Integer, Person> maxPersonById = records.stream()
    .collect(Collectors.toMap(Person::getId, Function.identity(),
        BinaryOperator.maxBy(Comparator.comparing(Person::getScore)
            .thenComparing(Comparator.comparing(Person::getOptionalId).reversed()))));

80分的分数怎么了?80分应该被删除。我只会从每组中取最高分。从上面的例子中,80分是最低的,有两个90分是最高的。我只会在两个最高的90分中取一个,以选择ID最低的为准。目前,max by从两个90分中随机取最高分我不知道want@TimBiegeleisen:消失。注意应用于分数的
收集器.maxBy
Optional
实际上是一个
java.util.Optional
?或
int/long
?如果分数相等,您永远不会检查可选值。Grrrr。更改比较器以使用该值应该不会很困难。I ta看一看。谢谢你的宝贵建议。我真的很感激。谢谢你的宝贵建议。我真的很感激。@TimBiegeleisen只有当你假设
OptionalId
确实是一个
long
,但它可能是一个
java.util.Optional
。@Eugene我不解释OP对这个词的使用“optional”指的是
optional
类,但二级ID只是一个op
Map<Integer, Person> maxPersonById = records.stream()
    .collect(Collectors.toMap(Person::getId, Function.identity(),
        BinaryOperator.maxBy(Comparator.comparing(Person::getScore)
            .thenComparing(Comparator.comparing(Person::getOptionalId).reversed()))));
{1=Person [id=1, score=90, optionalId=2], 2=Person [id=2, score=100, optionalId=3]}