简体   繁体   中英

How to store data in list of objects of an object?

I have the following code which group the users with same age and highest score among them. I have now instead of Map<Person, List<String>> one object called Person and in the person class there Map Map<String,Double> nameScoreTogether; . I need to store the output in the map of the person object with its informations(name and the corresponding score), so how can i change the code accordingly?

Input: In data type of 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}  

The Expected output is:

    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]

Try code: but now I have List<Person> which has 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()))
        );

Class Person:

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

I have changed the Person class as

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;
    }
}

I have added a new three parameter constructor.

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());

First, I map the input to a map of age to list of person, name entries.

Next, I stream it and compute the max score and map of person name to individual score and pass them as arguments to the Person constructor. Finally, I collect the individual Person objects as a list.

Note: This assumes that person name is unique.


UPDATE 1: From your comment,

[..] what if i have in person class instead of Map<String, Double> nameScoreTogether; a list of object like this: List<Information> nameScoreTogether and Information includes an attribute called String:name , and attribute called double:age

The Person class changes as

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
}

Information class:

private class Information {
    private String name;
    private double score;

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

Use the below block in place of //Find the map of name to score in the earlier provided code.

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

UPDATE 2:

If Information class only has a single argument constructor and a setter for score, change the map step as

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

Try this solution.

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));
            });

for above solution create this constructor in Person class

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

If you want a simple approach to solve your problem the go through the following snap code

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

// setter getter

}

Result Map as per your requirement You can convert these simple line of code into lambda expression very easily if

        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);
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM