问题
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;
}
回答1:
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 calledString:name
, and attribute calleddouble: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;
})
回答2:
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;
}
回答3:
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);
}
来源:https://stackoverflow.com/questions/62321819/how-to-store-data-in-list-of-objects-of-an-object