【问题标题】:How to find Top N given a list of Object?如何在给定对象列表的情况下找到前 N 个?
【发布时间】:2021-08-17 18:28:57
【问题描述】:

我想将键值对 存储在地图中,并根据以下逻辑根据 Key 的值(数据列表)对条目进行排序:

  1. 按数据对象中的分数对每个键(组)的值(列表中)进行排序,并
  2. 如果地图的大小大于 n(例如 n = 3) - 然后根据第一项的(值)分数对键(组)进行排序并返回 3。 - 相当于说获得前 3(每个中的 1组)基于高分

我希望每组(A、B、C、D)得到 1 个结果

 import java.util.ArrayList; 

public class MyClass {

    public static void main(String args[]) {
      
       // output should be just Data(17.0, "five", "D"), Data(4.0, "two", "A"), Data(3.0, "three", "B")
      ArrayList<Data> dataList = new ArrayList<Data>();
        dataList.add(new Data(1.0, "one", "A"));
        dataList.add(new Data(4.0, "two", "A"));
        dataList.add(new Data(3.0, "three", "B"));
        dataList.add(new Data(2.0, "four", "C"));
        dataList.add(new Data(7.0, "five", "D"));
        dataList.add(new Data(17.0, "five", "D"));
        
// output should be just Data(5.0, "six", "A"), Data(3.14, "two", "B"), Data(3.14, "three", "C")
      ArrayList<Data> dataList2 = new ArrayList<Data>();
        dataList2.add(new Data(3.0, "one", "A"));
        dataList2.add(new Data(5.0, "six", "A"));
        dataList2.add(new Data(3.14, "two", "B"));
        dataList2.add(new Data(3.14, "three", "C"));
        
      System.out.println("data 1=  " + dataList.size());
      System.out.println("data 2 =  " + dataList2.size());

    }
    
  static class Data {
     double score;
     String name; 
     String group;
     
      
    public Data(double score, String name, String group) {
        score = this.score;
        name = this.name;
        group = this.group;
    }
    
    public String getName() {
        return name;
    }
     
    public String getGroup() {
        return group;
    }
    
    public double getScore() {
        return score;
    }
    }
}

我知道执行此操作的程序方式,但在 Java 8 中是否有更智能/更实用的方式来执行此操作?

【问题讨论】:

  • 您在问题中提到的地图与您想要的结果有什么关系?我只能看到你对一个列表进行排序并输出具有最大属性值的 n 个元素。
  • @Eritrean 抱歉更新了问题。我正在寻找每组 1 个结果(A、B、C、D)
  • 我不明白。您说“键值对 ”,但“{"A", one, 3.0}" 没有列表。它看起来像一个列表本身或一个数组,但关键在哪里?您能否编辑您的问题,以便清楚“以下键值对”应该如何结束。哪个是关键,哪个是价值?
  • 请提供更多细节。显示前后(想要的结果),地图大于nn是什么? {"E", five, 2.1}, 在你的代码中在哪里?
  • @WJS 更新了这个问题。很抱歉造成混乱

标签: java java-8 priority-queue treemap treeset


【解决方案1】:

我希望每组(A、B、C、D)得到 1 个结果

我要存储键值对

以某种方式相互矛盾。但我假设您希望获得每个组中得分最高的条目,并将结果限制为某个给定大小n。如果这是真的,请尝试以下类似的方法来获取前 n 个元素的地图,其中 group 作为键,Data 对象本身作为值

long n = 3;

Map<String,Data> result =
            dataList.stream()
            .collect(Collectors.groupingBy(Data::getGroup,
                    Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingDouble(Data::getScore)),
                            Optional::get)))
            .entrySet()
            .stream()
                    .sorted(Comparator.comparing(e -> e.getValue().getScore(),Comparator.reverseOrder()))
                    .limit(n)
                    .collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue,(a,b) -> a, LinkedHashMap::new));

result.entrySet().forEach(System.out::println);

得到

D=MyClass.Data(score=17.0, name=five, group=D)
A=MyClass.Data(score=4.0, name=two, group=A)
B=MyClass.Data(score=3.0, name=three, group=B)

或者,如果您只需要包含每个组中最大分数元素的列表的子列表(因为组值在对象本身中可用),则执行以下操作:

List<Data> result =
            dataList.stream()
            .collect(Collectors.groupingBy(Data::getGroup,
                    Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingDouble(Data::getScore)),
                            Optional::get)))
            .values()
            .stream()
                    .sorted(Comparator.comparingDouble(Data::getScore).reversed())
                    .limit(n)
                    .collect(Collectors.toList());
    result.forEach(System.out::println);

result.forEach(System.out::println);

得到

MyClass.Data(score=17.0, name=five, group=D)
MyClass.Data(score=4.0, name=two, group=A)
MyClass.Data(score=3.0, name=three, group=B)

【讨论】:

  • 是的!假设是正确的,但这如何给我 top n 呢?如果 n = 3
  • 恐怕我还不确定你想要的最终结果应该是什么。您能否为示例列表dataListn = 3 提供所需的结果?包含分值为 17、4 和 3 的元素的子列表?以组为键、值为 ??? 的映射还是别的什么?
  • @Eritrean 恐怕我还不确定你想要的最终结果应该是什么。您能否为您的示例列表 dataList 提供所需的结果,其中 n = 3? 那您为什么在得到澄清之前尝试回答?
  • @WJS 这个问题已经被编辑了好几次,并且已经添加了 cmets,尽管进行了编辑,但一开始似乎很清楚的要求和期望的最终结果对我来说变得相当不清楚。因此,我尝试向 OP 提供他正在寻找的东西,但未能准确地表达出他真正想要的东西。一种预测性的回复:-)。但是 OP 也可能有 xy 问题。
  • 您可以使用不需要处理OptionalCollectors.toMap(Data::getGroup, Function.identity(), BinaryOperator.maxBy(Comparator.comparingDouble(Data::getScore))) 而不是Collectors.groupingBy(Data::getGroup, Collectors.collectingAndThen( Collectors.maxBy(Comparator.comparingDouble(Data::getScore)), Optional::get))。另见Java Streams: Replacing groupingBy and reducing by toMap
猜你喜欢
  • 2014-01-06
  • 1970-01-01
  • 1970-01-01
  • 2015-05-17
  • 2014-07-31
  • 2021-05-18
  • 2014-03-04
  • 1970-01-01
相关资源
最近更新 更多