【问题标题】:How to store data in list of objects of an object?如何将数据存储在对象的对象列表中?
【发布时间】:2020-09-30 22:41:25
【问题描述】:

我有以下代码将年龄相同且得分最高的用户分组。 我现在有一个名为 Person 的对象而不是 Map<Person, List<String>>,并且在 person 类中有 Map Map<String,Double> nameScoreTogether;。我需要将输出及其信息(名称和相应的分数)存储在 person 对象的映射中,那么我该如何相应地更改代码?

输入:在Map<Person, String>的数据类型中:

    {Person has at Age: 12 (Score: 50)
    =alex,
     Person has at Age: 16 (Score: 50)
    =miki, 
    Person has at Age: 5 (Score: 100)
    =shi, 
    Person has at Age: 4 (Score: 50)
    =rafi, 
    Person has at Age: 1 (Score: 50)
    =sharbel, 
    Person has at Age: 5 (Score: 0)
    =thomas, 
    Person has at Age: 14 (Score: 60)
    =thomy, 
    Person has at Age: 14 (Score: 50)
    =angelos,
     Person has at Age: 11 (Score: 50)
    =musti, 
    Person has at Age: 11 (Score: 100)
    =aloo,
     Person has at Age: 2 (Score: 50)
    =evi}  

预期的输出是:

    Person(score=50.0, age=1) - [sharbel=50.0]
    Person(score=100.0, age=11) - [aloo=100.0, musti=50.0]
    Person(score=50.0, age=12) - [Alex=50.0]
    Person(score=60.0, age=14) - [thomy=60.0, angelos=50.0]
    Person(score=50.0, age=2) - [evi=50.0]
    Person(score=100.0, age=5) - [shi=100.0, Thomas=5.0]
    Person(score=50.0, age=4) - [rafi=50]
    Person(score=50.0, age=16) - [miki=50]

尝试代码:但现在我有List<Person>,其中有Map<String,Double>

    Map<Person, List<String>> result = origin.entrySet().stream()
        .collect(Collectors.groupingBy(e -> e.getKey().getAge())).entrySet().stream()
        .collect(Collectors.toMap(
            e -> e.getValue().stream()
                .map(Map.Entry::getKey)
                .max(Comparator.comparing(Person::getScore))
                .get(),
            e -> e.getValue().stream()
                .map(Map.Entry::getValue)
                .collect(Collectors.toList()))
        );

类人:

    public class Person {
        int Age;
        int lineScoreMax;
        Map<String, Double> nameScoreTogether;
    }

【问题讨论】:

  • 如果我知道您有 Map&lt;Person, String&gt; 并且您想将其转换为 Map&lt;Person, List&lt;String&gt;&gt; ?
  • 不,我想将其转换为 List
  • 所以每个人都有 lineScore 这是最高分数,包括元组人名列表及其分数
  • 你能修正你的输入和预期的输出吗? Person has at Age: 1 (Score: 50). (Score: 50) =sharbel,为什么这一行有两个Score?
  • 更新帖子

标签: java arrays algorithm hashmap


【解决方案1】:

试试这个解决方案。

List<Person> persons = new ArrayList<>();
    personAndNameMap.entrySet().stream()
            // collect the list of persons group by age (it collect list of persons with same age)
            .collect(Collectors.groupingBy(e -> e.getKey().getAge()))
            // iterate the persons of same age
            .forEach((key, value) -> {
                // set the best score to 0 among them
                double bestScore = 0;
                // create a map to store name and their line score
                Map<String, Double> nameAndScoreMap = new HashMap<>();
                for (Map.Entry<Person, String> map : value) {
                    // check and update best score
                    bestScore = Math.max(bestScore, map.getKey().getLineScoreMax());
                    // add person name and his line score in map
                    nameAndScoreMap.put(map.getValue(), map.getKey().getLineScoreMax());
                }
                // add the person in list
                persons.add(new Person(key, bestScore, nameAndScoreMap));
            });

对于上述解决方案,在 Person 类中创建此构造函数

public Person(int age, double lineScoreMax, Map<String, Double> nameAndScoreMap) {
    this.age = age;
    this.lineScoreMax = lineScoreMax;
    this.nameAndScoreMap = nameAndScoreMap;
}

【讨论】:

  • 我认为一个人的最低分数可能为 0。如果允许 -ve 分数,则将 bestScore 初始化为 Double.MIN_VALUE。
【解决方案2】:

如果您想要一种简单的方法来解决您的问题,请查看以下快照代码

// class 
class Person{
    int age;
    double linescoreMax;
    Map<String, Double> nameScoreTogether;

// setter getter

}

根据您的要求的结果图 如果

        Map<Integer, Person> resultMap = new HashMap<>();

//      Repeat for each inputs :  inputName, inputAge, inputScore

        if (resultMap.containsKey(inputAge)) {
            Person person = resultMap.get(inputAge);
            if (inputScore > person.getLinescoreMax()) {
                person.setLinescoreMax(inputScore);
            }
            person.getNameScoreTogether().put(inputName, inputScore);
        } else {
            Person p = new Person();
            Map<String, Double> pMap = new HashMap<>();
            pMap.put(inputName, inputScore);

            p.setAge(inputAge);
            p.setLinescoreMax(inputScore);
            p.setNameScoreTogether(pMap);

            resultMap.put(p.getAge(), p);
        }

【讨论】:

    【解决方案3】:

    我已将Person 类更改为

    public class Person {
        int age;
        double lineScoreMax;
        Map<String, Double> nameScoreTogether;
    
        Person(int age, double score) {
            this.age = age;
            this.lineScoreMax = score;
        }
    
        Person(int age, double score,  Map<String, Double> nameScoreTogether) {
            this.age = age;
            this.lineScoreMax = score;
            this.nameScoreTogether = nameScoreTogether;
        }
    
        public int getAge() {
            return age;
        }
    
        public double getLineScoreMax() {
            return lineScoreMax;
        }
    }
    

    我添加了一个新的三参数构造函数。

    Map<Person, String> origin = new HashMap();
    //Populate origin
    
    Map<Integer, List<Map.Entry<Person, String>>> ageToListOfPersonNames = origin.entrySet()
                .stream()
                .collect(Collectors.groupingBy(entry -> entry.getKey().getAge()));
    
    List<Person> persons = ageToListOfPersonNames.entrySet()
            .stream()
            .map(entry -> new Person(entry.getKey(),
                    //Find the max score for an age
                    entry.getValue()
                         .stream()
                         .map(Map.Entry::getKey)
                            .max(Comparator.comparingDouble(Person::getLineScoreMax))
                            .map(Person::getLineScoreMax)
                            .orElse(0D),
    
                    //Find the map of name to score
                    entry.getValue()
                            .stream()
                            .collect(Collectors.toMap(Map.Entry::getValue,
                                    personNameEntry -> personNameEntry.getKey().getLineScoreMax()))
                ))
            .collect(Collectors.toList());
    

    首先,我将输入映射到年龄映射到 person, name 条目列表。

    接下来,我将其流式传输并计算最大分数和人名到个人分数的映射,并将它们作为参数传递给 Person 构造函数。最后,我将各个 Person 对象收集为一个列表。

    注意:这假定人名是唯一的。


    更新 1: 根据您的评论,

    [..] 如果我有亲自上课而不是Map&lt;String, Double&gt; nameScoreTogether;像这样的对象列表:List&lt;Information&gt; nameScoreTogether 和 Information 包括一个名为 String:name 的属性和名为 double:age 的属性

    Person 类更改为

    public class Person {
        int age;
        double lineScoreMax;
        List<Information> nameScoreTogether;
    
        Person(int age, double score) {
            this.age = age;
            this.lineScoreMax = score;
        }
    
        Person(int age, double score,  List<Information> nameScoreTogether) {
            this.age = age;
            this.lineScoreMax = score;
            this.nameScoreTogether = nameScoreTogether;
        }
        //Getters
    }
    

    信息类:

    private class Information {
        private String name;
        private double score;
    
       Information(String name, double score) {
            this.name = name;
            this.score = score;
        }
    }
    

    在前面提供的代码中使用下面的块代替//Find the map of name to score。

    entry.getValue()
         .stream()
         .map(personNameEntry -> new Information(personNameEntry.getValue(),
                                personNameEntry.getKey().getLineScoreMax()))
         .collect(Collectors.toList())
    

    更新 2:

    如果 Information 类只有一个参数构造函数和一个分数设置器,请将map 步骤更改为

    .map(personNameEntry -> {
        Information information = new Information(personNameEntry.getValue());
        information.setScore(personNameEntry.getKey().getLineScoreMax());
        return information;
      })
    

    【讨论】:

    • 感谢您的解决方案:我有一个问题:如果我有面对面的类而不是 Map&lt;String, Double&gt; nameScoreTogether; 一个像这样的对象列表:List&lt;Information&gt; nameScoreTogether 并且信息包括一个名为 @987654336 的属性@,以及名为 double:age 的属性,您能否在上面的解决方案下添加此变体?
    • @Catalina 查看我的编辑。我只给出了计算 Person 类的第三个参数的部分。其余代码保持不变。
    • 谢谢,对不起,我忘了说 Information 的分数只能通过 setter 方法访问。我们只能像这样创建一个类信息对象:new Information("name"),并且要设置分数,我们必须使用 setter mthode。 setScore()
    • 这将是我最后一次更改请求
    • 我已经展示了如何更改地图块。但是拥有一个带有两个参数的构造函数会更好更整洁。以后避免问多个问题。这里不建议。
    猜你喜欢
    • 1970-01-01
    • 2021-08-27
    • 2021-12-13
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多