Grouping and Double sorting List
I went through all the manuals out there and all SO questions but still unable to figure this out...
I have a List (integer represents age):
List<Person> people = Arrays.asList
(
new Person("bob", 10),
new Person("sue", 4),
new Person("tom", 37),
new Person("jim", 10),
new Person("boo", 4),
new Person("ekk", 53),
new Person("joe", 10)
);
I need to:
- group the list by age,
- sort by group sizes (descending),
- sort by age (descending)
So using the example above the result would have to be like this:
{10=[bob, jim, joe],4=[sue, boo], 53=[ekk], 37=[tom]}
What I tried:
I tried with and without streams. I failed on both.
Note: I would lean toward no stream solution, because from my testing of the below code it seems like streams are much slower (I used System.nanotime()). These 3 operations will be done thousands of times each time, so it may make a slight difference.
Using streams here is what I did:
List<List<Person>> grpd = new ArrayList<>
(
people.stream()
.collect
(
groupingBy(Person::getAge, toList())
)
.values()
);
grpd = grpd.stream().sorted((a, b) -> Integer.compare(b.size(), a.size())).collect(toList());
No streams approach:
Map<Integer, List<Person>> grouped = new HashMap<>();
for (Person person : people)
{
if (grouped.containsKey(person._age))
{
grouped.get(person._age).add(person);
} else
{
List<Person> p = new ArrayList<>();
p.add(person);
grouped.put(person._age, p);
}
}
List<Map.Entry<Integer, List<Person>>> entries = new ArrayList<>(grouped.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<Integer, List<Person>>>()
{
@Override
public int compare(Map.Entry<Integer, List<Person>> o1, Map.Entry<Integer, List<Person>> o2)
{
return Integer.compare(o2.getValue().size(), o1.getValue().size());
}
});
Map<Integer, List<Person>> sortedBySize = new LinkedHashMap<>();
for (Map.Entry<Integer, List<Person>> entry : entries)
{
sortedBySize.put(entry.getKey(), entry.getValue());
}
Problem:
I have no idea how to add the final sort on either case.
public class Person
{
public String _name;
public int _age;
public int getAge() { return _age; }
public Person(String name, int age)
{
_name = name;
_age = age;
}
@Override
public String toString()
{
return _name;
}
}
java sorting
add a comment |
I went through all the manuals out there and all SO questions but still unable to figure this out...
I have a List (integer represents age):
List<Person> people = Arrays.asList
(
new Person("bob", 10),
new Person("sue", 4),
new Person("tom", 37),
new Person("jim", 10),
new Person("boo", 4),
new Person("ekk", 53),
new Person("joe", 10)
);
I need to:
- group the list by age,
- sort by group sizes (descending),
- sort by age (descending)
So using the example above the result would have to be like this:
{10=[bob, jim, joe],4=[sue, boo], 53=[ekk], 37=[tom]}
What I tried:
I tried with and without streams. I failed on both.
Note: I would lean toward no stream solution, because from my testing of the below code it seems like streams are much slower (I used System.nanotime()). These 3 operations will be done thousands of times each time, so it may make a slight difference.
Using streams here is what I did:
List<List<Person>> grpd = new ArrayList<>
(
people.stream()
.collect
(
groupingBy(Person::getAge, toList())
)
.values()
);
grpd = grpd.stream().sorted((a, b) -> Integer.compare(b.size(), a.size())).collect(toList());
No streams approach:
Map<Integer, List<Person>> grouped = new HashMap<>();
for (Person person : people)
{
if (grouped.containsKey(person._age))
{
grouped.get(person._age).add(person);
} else
{
List<Person> p = new ArrayList<>();
p.add(person);
grouped.put(person._age, p);
}
}
List<Map.Entry<Integer, List<Person>>> entries = new ArrayList<>(grouped.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<Integer, List<Person>>>()
{
@Override
public int compare(Map.Entry<Integer, List<Person>> o1, Map.Entry<Integer, List<Person>> o2)
{
return Integer.compare(o2.getValue().size(), o1.getValue().size());
}
});
Map<Integer, List<Person>> sortedBySize = new LinkedHashMap<>();
for (Map.Entry<Integer, List<Person>> entry : entries)
{
sortedBySize.put(entry.getKey(), entry.getValue());
}
Problem:
I have no idea how to add the final sort on either case.
public class Person
{
public String _name;
public int _age;
public int getAge() { return _age; }
public Person(String name, int age)
{
_name = name;
_age = age;
}
@Override
public String toString()
{
return _name;
}
}
java sorting
add a comment |
I went through all the manuals out there and all SO questions but still unable to figure this out...
I have a List (integer represents age):
List<Person> people = Arrays.asList
(
new Person("bob", 10),
new Person("sue", 4),
new Person("tom", 37),
new Person("jim", 10),
new Person("boo", 4),
new Person("ekk", 53),
new Person("joe", 10)
);
I need to:
- group the list by age,
- sort by group sizes (descending),
- sort by age (descending)
So using the example above the result would have to be like this:
{10=[bob, jim, joe],4=[sue, boo], 53=[ekk], 37=[tom]}
What I tried:
I tried with and without streams. I failed on both.
Note: I would lean toward no stream solution, because from my testing of the below code it seems like streams are much slower (I used System.nanotime()). These 3 operations will be done thousands of times each time, so it may make a slight difference.
Using streams here is what I did:
List<List<Person>> grpd = new ArrayList<>
(
people.stream()
.collect
(
groupingBy(Person::getAge, toList())
)
.values()
);
grpd = grpd.stream().sorted((a, b) -> Integer.compare(b.size(), a.size())).collect(toList());
No streams approach:
Map<Integer, List<Person>> grouped = new HashMap<>();
for (Person person : people)
{
if (grouped.containsKey(person._age))
{
grouped.get(person._age).add(person);
} else
{
List<Person> p = new ArrayList<>();
p.add(person);
grouped.put(person._age, p);
}
}
List<Map.Entry<Integer, List<Person>>> entries = new ArrayList<>(grouped.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<Integer, List<Person>>>()
{
@Override
public int compare(Map.Entry<Integer, List<Person>> o1, Map.Entry<Integer, List<Person>> o2)
{
return Integer.compare(o2.getValue().size(), o1.getValue().size());
}
});
Map<Integer, List<Person>> sortedBySize = new LinkedHashMap<>();
for (Map.Entry<Integer, List<Person>> entry : entries)
{
sortedBySize.put(entry.getKey(), entry.getValue());
}
Problem:
I have no idea how to add the final sort on either case.
public class Person
{
public String _name;
public int _age;
public int getAge() { return _age; }
public Person(String name, int age)
{
_name = name;
_age = age;
}
@Override
public String toString()
{
return _name;
}
}
java sorting
I went through all the manuals out there and all SO questions but still unable to figure this out...
I have a List (integer represents age):
List<Person> people = Arrays.asList
(
new Person("bob", 10),
new Person("sue", 4),
new Person("tom", 37),
new Person("jim", 10),
new Person("boo", 4),
new Person("ekk", 53),
new Person("joe", 10)
);
I need to:
- group the list by age,
- sort by group sizes (descending),
- sort by age (descending)
So using the example above the result would have to be like this:
{10=[bob, jim, joe],4=[sue, boo], 53=[ekk], 37=[tom]}
What I tried:
I tried with and without streams. I failed on both.
Note: I would lean toward no stream solution, because from my testing of the below code it seems like streams are much slower (I used System.nanotime()). These 3 operations will be done thousands of times each time, so it may make a slight difference.
Using streams here is what I did:
List<List<Person>> grpd = new ArrayList<>
(
people.stream()
.collect
(
groupingBy(Person::getAge, toList())
)
.values()
);
grpd = grpd.stream().sorted((a, b) -> Integer.compare(b.size(), a.size())).collect(toList());
No streams approach:
Map<Integer, List<Person>> grouped = new HashMap<>();
for (Person person : people)
{
if (grouped.containsKey(person._age))
{
grouped.get(person._age).add(person);
} else
{
List<Person> p = new ArrayList<>();
p.add(person);
grouped.put(person._age, p);
}
}
List<Map.Entry<Integer, List<Person>>> entries = new ArrayList<>(grouped.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<Integer, List<Person>>>()
{
@Override
public int compare(Map.Entry<Integer, List<Person>> o1, Map.Entry<Integer, List<Person>> o2)
{
return Integer.compare(o2.getValue().size(), o1.getValue().size());
}
});
Map<Integer, List<Person>> sortedBySize = new LinkedHashMap<>();
for (Map.Entry<Integer, List<Person>> entry : entries)
{
sortedBySize.put(entry.getKey(), entry.getValue());
}
Problem:
I have no idea how to add the final sort on either case.
public class Person
{
public String _name;
public int _age;
public int getAge() { return _age; }
public Person(String name, int age)
{
_name = name;
_age = age;
}
@Override
public String toString()
{
return _name;
}
}
java sorting
java sorting
edited Nov 19 '18 at 19:12
asked Nov 19 '18 at 12:49
CallMeBob
2,64721530
2,64721530
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
As you've also asked about a non-stream solution, here it is:
Map<Integer, List<Person>> grouped = new HashMap<>();
people.forEach(person -> grouped.computeIfAbsent(
person.getAge(),
k -> new ArrayList<>())
.add(person));
This groups by age. Now let's sort the entries, first by group size descending, then by age descending:
List<Map.Entry<Integer, List<Person>>> toSort = new ArrayList<>(grouped.entrySet());
toSort.sort(
Comparator.comparingInt((Map.Entry<Integer, List<Person>> e) -> e.getValue().size())
.reversed()
.thenComparingInt(Map.Entry.comparingByKey().reversed()));
Now, toSort
is a sorted list of entries. You need to put those entries into a new map:
Map<Integer, List<Person>> sorted = new LinkedHashMap<>();
toSort.forEach(e -> sorted.put(e.getKey(), e.getValue()));
And sorted
holds the result you want.
Nice and quick! Thanks :)
– CallMeBob
Nov 19 '18 at 16:43
add a comment |
Use streams.
First, group them by age:
Map<Integer, List<Person>> groupedByAge =
people.stream().collect(groupingBy(Person::getAge));
Then sort the entries of this map:
Comparator<Map.Entry<Integer, List<Person>>> byCount = comparingInt(e -> e.getValue().size());
Comparator<Map.Entry<Integer, List<Person>>> byAge = comparingInt(Map.Entry::getKey);
Stream<Map.Entry<Integer, List<Person>>> sorted =
groupedByAge.entrySet().stream().sorted(byCount.reversed().thenComparing(byAge.reversed()));
Then just get the list out of there:
List<List<Person>> result = sorted.map(Map.Entry::getValue).collect(toList());
(You can put this all into a single expression, but I claim it is more readable broken out like this).
thanks for quick reply. It doesn't seem to understand e.getValue() and e.getKey() though - 'Cannot resolve method'.
– CallMeBob
Nov 19 '18 at 12:58
So add some more type information.
– Andy Turner
Nov 19 '18 at 12:59
Yes, seems to work the magic! Many thanks. I spend unseasonable amount of time on it before posting here. You cracked it in 5 minutes... :)
– CallMeBob
Nov 19 '18 at 13:09
add a comment |
Since you were also looking for a non-stream solution:
public static Map<Integer, List<Person>> group(List<Person> people) {
Map<Integer, List<Person>> intermediateGrouping = new HashMap<>();
for (Person person : people) {
intermediateGrouping.computeIfAbsent(person.getAge(), k -> new ArrayList<>()).add(person);
}
Comparator<Entry<Integer, List<Person>>> byGroupSize = Entry.comparingByValue(Comparator.comparingInt(List::size));
Comparator<Entry<Integer, List<Person>>> byAge = Entry.comparingByKey();
List<Entry<Integer, List<Person>>> entries = new ArrayList<>(intermediateGrouping.entrySet());
entries.sort(byGroupSize.reversed().thenComparing(byAge.reversed()));
Map<Integer, List<Person>> result = new LinkedHashMap<>(entries.size());
for (Entry<Integer, List<Person>> entry : entries) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
Or if you prefer the result to be a List<List<Person>>
:
public static List<List<Person>> group(List<Person> people) {
Map<Integer, List<Person>> intermediateGrouping = new HashMap<>();
for (Person person : people) {
intermediateGrouping.computeIfAbsent(person.getAge(), k -> new ArrayList<>()).add(person);
}
Comparator<Entry<Integer, List<Person>>> byGroupSize = Entry.comparingByValue(Comparator.comparingInt(List::size));
Comparator<Entry<Integer, List<Person>>> byAge = Entry.comparingByKey();
List<Entry<Integer, List<Person>>> entries = new ArrayList<>(intermediateGrouping.entrySet());
entries.sort(byGroupSize.reversed().thenComparing(byAge.reversed()));
List<List<Person>> result = new ArrayList<>(entries.size());
for (Entry<Integer, List<Person>> entry : entries) {
result.add(entry.getValue());
}
return result;
}
add a comment |
Try modifiying your sort comparator using the below implementation when the sizes are equal for a no streams approach
Collections.sort(entries, new Comparator<Map.Entry<Integer, List<Person>>>()
{
@Override
public int compare(Map.Entry<Integer, List<Person>> o1, Map.Entry<Integer, List<Person>> o2)
{
if(o1.getValue().size()<o2.getValue().size())
return 1;
else if(o1.getValue().size()>o2.getValue().size())
return -1;
else {
if( o1.getKey()< o2.getKey())
return 1;
else if(o1.getKey()>o2.getKey())
return -1;
else
return 0;
}
}
});
Let me know if it works on all your Test Cases
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53375009%2fgrouping-and-double-sorting-listperson%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
As you've also asked about a non-stream solution, here it is:
Map<Integer, List<Person>> grouped = new HashMap<>();
people.forEach(person -> grouped.computeIfAbsent(
person.getAge(),
k -> new ArrayList<>())
.add(person));
This groups by age. Now let's sort the entries, first by group size descending, then by age descending:
List<Map.Entry<Integer, List<Person>>> toSort = new ArrayList<>(grouped.entrySet());
toSort.sort(
Comparator.comparingInt((Map.Entry<Integer, List<Person>> e) -> e.getValue().size())
.reversed()
.thenComparingInt(Map.Entry.comparingByKey().reversed()));
Now, toSort
is a sorted list of entries. You need to put those entries into a new map:
Map<Integer, List<Person>> sorted = new LinkedHashMap<>();
toSort.forEach(e -> sorted.put(e.getKey(), e.getValue()));
And sorted
holds the result you want.
Nice and quick! Thanks :)
– CallMeBob
Nov 19 '18 at 16:43
add a comment |
As you've also asked about a non-stream solution, here it is:
Map<Integer, List<Person>> grouped = new HashMap<>();
people.forEach(person -> grouped.computeIfAbsent(
person.getAge(),
k -> new ArrayList<>())
.add(person));
This groups by age. Now let's sort the entries, first by group size descending, then by age descending:
List<Map.Entry<Integer, List<Person>>> toSort = new ArrayList<>(grouped.entrySet());
toSort.sort(
Comparator.comparingInt((Map.Entry<Integer, List<Person>> e) -> e.getValue().size())
.reversed()
.thenComparingInt(Map.Entry.comparingByKey().reversed()));
Now, toSort
is a sorted list of entries. You need to put those entries into a new map:
Map<Integer, List<Person>> sorted = new LinkedHashMap<>();
toSort.forEach(e -> sorted.put(e.getKey(), e.getValue()));
And sorted
holds the result you want.
Nice and quick! Thanks :)
– CallMeBob
Nov 19 '18 at 16:43
add a comment |
As you've also asked about a non-stream solution, here it is:
Map<Integer, List<Person>> grouped = new HashMap<>();
people.forEach(person -> grouped.computeIfAbsent(
person.getAge(),
k -> new ArrayList<>())
.add(person));
This groups by age. Now let's sort the entries, first by group size descending, then by age descending:
List<Map.Entry<Integer, List<Person>>> toSort = new ArrayList<>(grouped.entrySet());
toSort.sort(
Comparator.comparingInt((Map.Entry<Integer, List<Person>> e) -> e.getValue().size())
.reversed()
.thenComparingInt(Map.Entry.comparingByKey().reversed()));
Now, toSort
is a sorted list of entries. You need to put those entries into a new map:
Map<Integer, List<Person>> sorted = new LinkedHashMap<>();
toSort.forEach(e -> sorted.put(e.getKey(), e.getValue()));
And sorted
holds the result you want.
As you've also asked about a non-stream solution, here it is:
Map<Integer, List<Person>> grouped = new HashMap<>();
people.forEach(person -> grouped.computeIfAbsent(
person.getAge(),
k -> new ArrayList<>())
.add(person));
This groups by age. Now let's sort the entries, first by group size descending, then by age descending:
List<Map.Entry<Integer, List<Person>>> toSort = new ArrayList<>(grouped.entrySet());
toSort.sort(
Comparator.comparingInt((Map.Entry<Integer, List<Person>> e) -> e.getValue().size())
.reversed()
.thenComparingInt(Map.Entry.comparingByKey().reversed()));
Now, toSort
is a sorted list of entries. You need to put those entries into a new map:
Map<Integer, List<Person>> sorted = new LinkedHashMap<>();
toSort.forEach(e -> sorted.put(e.getKey(), e.getValue()));
And sorted
holds the result you want.
edited Nov 19 '18 at 15:58
answered Nov 19 '18 at 13:31


Federico Peralta Schaffner
21.9k43370
21.9k43370
Nice and quick! Thanks :)
– CallMeBob
Nov 19 '18 at 16:43
add a comment |
Nice and quick! Thanks :)
– CallMeBob
Nov 19 '18 at 16:43
Nice and quick! Thanks :)
– CallMeBob
Nov 19 '18 at 16:43
Nice and quick! Thanks :)
– CallMeBob
Nov 19 '18 at 16:43
add a comment |
Use streams.
First, group them by age:
Map<Integer, List<Person>> groupedByAge =
people.stream().collect(groupingBy(Person::getAge));
Then sort the entries of this map:
Comparator<Map.Entry<Integer, List<Person>>> byCount = comparingInt(e -> e.getValue().size());
Comparator<Map.Entry<Integer, List<Person>>> byAge = comparingInt(Map.Entry::getKey);
Stream<Map.Entry<Integer, List<Person>>> sorted =
groupedByAge.entrySet().stream().sorted(byCount.reversed().thenComparing(byAge.reversed()));
Then just get the list out of there:
List<List<Person>> result = sorted.map(Map.Entry::getValue).collect(toList());
(You can put this all into a single expression, but I claim it is more readable broken out like this).
thanks for quick reply. It doesn't seem to understand e.getValue() and e.getKey() though - 'Cannot resolve method'.
– CallMeBob
Nov 19 '18 at 12:58
So add some more type information.
– Andy Turner
Nov 19 '18 at 12:59
Yes, seems to work the magic! Many thanks. I spend unseasonable amount of time on it before posting here. You cracked it in 5 minutes... :)
– CallMeBob
Nov 19 '18 at 13:09
add a comment |
Use streams.
First, group them by age:
Map<Integer, List<Person>> groupedByAge =
people.stream().collect(groupingBy(Person::getAge));
Then sort the entries of this map:
Comparator<Map.Entry<Integer, List<Person>>> byCount = comparingInt(e -> e.getValue().size());
Comparator<Map.Entry<Integer, List<Person>>> byAge = comparingInt(Map.Entry::getKey);
Stream<Map.Entry<Integer, List<Person>>> sorted =
groupedByAge.entrySet().stream().sorted(byCount.reversed().thenComparing(byAge.reversed()));
Then just get the list out of there:
List<List<Person>> result = sorted.map(Map.Entry::getValue).collect(toList());
(You can put this all into a single expression, but I claim it is more readable broken out like this).
thanks for quick reply. It doesn't seem to understand e.getValue() and e.getKey() though - 'Cannot resolve method'.
– CallMeBob
Nov 19 '18 at 12:58
So add some more type information.
– Andy Turner
Nov 19 '18 at 12:59
Yes, seems to work the magic! Many thanks. I spend unseasonable amount of time on it before posting here. You cracked it in 5 minutes... :)
– CallMeBob
Nov 19 '18 at 13:09
add a comment |
Use streams.
First, group them by age:
Map<Integer, List<Person>> groupedByAge =
people.stream().collect(groupingBy(Person::getAge));
Then sort the entries of this map:
Comparator<Map.Entry<Integer, List<Person>>> byCount = comparingInt(e -> e.getValue().size());
Comparator<Map.Entry<Integer, List<Person>>> byAge = comparingInt(Map.Entry::getKey);
Stream<Map.Entry<Integer, List<Person>>> sorted =
groupedByAge.entrySet().stream().sorted(byCount.reversed().thenComparing(byAge.reversed()));
Then just get the list out of there:
List<List<Person>> result = sorted.map(Map.Entry::getValue).collect(toList());
(You can put this all into a single expression, but I claim it is more readable broken out like this).
Use streams.
First, group them by age:
Map<Integer, List<Person>> groupedByAge =
people.stream().collect(groupingBy(Person::getAge));
Then sort the entries of this map:
Comparator<Map.Entry<Integer, List<Person>>> byCount = comparingInt(e -> e.getValue().size());
Comparator<Map.Entry<Integer, List<Person>>> byAge = comparingInt(Map.Entry::getKey);
Stream<Map.Entry<Integer, List<Person>>> sorted =
groupedByAge.entrySet().stream().sorted(byCount.reversed().thenComparing(byAge.reversed()));
Then just get the list out of there:
List<List<Person>> result = sorted.map(Map.Entry::getValue).collect(toList());
(You can put this all into a single expression, but I claim it is more readable broken out like this).
edited Nov 19 '18 at 13:24
answered Nov 19 '18 at 12:53
Andy Turner
80.4k880134
80.4k880134
thanks for quick reply. It doesn't seem to understand e.getValue() and e.getKey() though - 'Cannot resolve method'.
– CallMeBob
Nov 19 '18 at 12:58
So add some more type information.
– Andy Turner
Nov 19 '18 at 12:59
Yes, seems to work the magic! Many thanks. I spend unseasonable amount of time on it before posting here. You cracked it in 5 minutes... :)
– CallMeBob
Nov 19 '18 at 13:09
add a comment |
thanks for quick reply. It doesn't seem to understand e.getValue() and e.getKey() though - 'Cannot resolve method'.
– CallMeBob
Nov 19 '18 at 12:58
So add some more type information.
– Andy Turner
Nov 19 '18 at 12:59
Yes, seems to work the magic! Many thanks. I spend unseasonable amount of time on it before posting here. You cracked it in 5 minutes... :)
– CallMeBob
Nov 19 '18 at 13:09
thanks for quick reply. It doesn't seem to understand e.getValue() and e.getKey() though - 'Cannot resolve method'.
– CallMeBob
Nov 19 '18 at 12:58
thanks for quick reply. It doesn't seem to understand e.getValue() and e.getKey() though - 'Cannot resolve method'.
– CallMeBob
Nov 19 '18 at 12:58
So add some more type information.
– Andy Turner
Nov 19 '18 at 12:59
So add some more type information.
– Andy Turner
Nov 19 '18 at 12:59
Yes, seems to work the magic! Many thanks. I spend unseasonable amount of time on it before posting here. You cracked it in 5 minutes... :)
– CallMeBob
Nov 19 '18 at 13:09
Yes, seems to work the magic! Many thanks. I spend unseasonable amount of time on it before posting here. You cracked it in 5 minutes... :)
– CallMeBob
Nov 19 '18 at 13:09
add a comment |
Since you were also looking for a non-stream solution:
public static Map<Integer, List<Person>> group(List<Person> people) {
Map<Integer, List<Person>> intermediateGrouping = new HashMap<>();
for (Person person : people) {
intermediateGrouping.computeIfAbsent(person.getAge(), k -> new ArrayList<>()).add(person);
}
Comparator<Entry<Integer, List<Person>>> byGroupSize = Entry.comparingByValue(Comparator.comparingInt(List::size));
Comparator<Entry<Integer, List<Person>>> byAge = Entry.comparingByKey();
List<Entry<Integer, List<Person>>> entries = new ArrayList<>(intermediateGrouping.entrySet());
entries.sort(byGroupSize.reversed().thenComparing(byAge.reversed()));
Map<Integer, List<Person>> result = new LinkedHashMap<>(entries.size());
for (Entry<Integer, List<Person>> entry : entries) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
Or if you prefer the result to be a List<List<Person>>
:
public static List<List<Person>> group(List<Person> people) {
Map<Integer, List<Person>> intermediateGrouping = new HashMap<>();
for (Person person : people) {
intermediateGrouping.computeIfAbsent(person.getAge(), k -> new ArrayList<>()).add(person);
}
Comparator<Entry<Integer, List<Person>>> byGroupSize = Entry.comparingByValue(Comparator.comparingInt(List::size));
Comparator<Entry<Integer, List<Person>>> byAge = Entry.comparingByKey();
List<Entry<Integer, List<Person>>> entries = new ArrayList<>(intermediateGrouping.entrySet());
entries.sort(byGroupSize.reversed().thenComparing(byAge.reversed()));
List<List<Person>> result = new ArrayList<>(entries.size());
for (Entry<Integer, List<Person>> entry : entries) {
result.add(entry.getValue());
}
return result;
}
add a comment |
Since you were also looking for a non-stream solution:
public static Map<Integer, List<Person>> group(List<Person> people) {
Map<Integer, List<Person>> intermediateGrouping = new HashMap<>();
for (Person person : people) {
intermediateGrouping.computeIfAbsent(person.getAge(), k -> new ArrayList<>()).add(person);
}
Comparator<Entry<Integer, List<Person>>> byGroupSize = Entry.comparingByValue(Comparator.comparingInt(List::size));
Comparator<Entry<Integer, List<Person>>> byAge = Entry.comparingByKey();
List<Entry<Integer, List<Person>>> entries = new ArrayList<>(intermediateGrouping.entrySet());
entries.sort(byGroupSize.reversed().thenComparing(byAge.reversed()));
Map<Integer, List<Person>> result = new LinkedHashMap<>(entries.size());
for (Entry<Integer, List<Person>> entry : entries) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
Or if you prefer the result to be a List<List<Person>>
:
public static List<List<Person>> group(List<Person> people) {
Map<Integer, List<Person>> intermediateGrouping = new HashMap<>();
for (Person person : people) {
intermediateGrouping.computeIfAbsent(person.getAge(), k -> new ArrayList<>()).add(person);
}
Comparator<Entry<Integer, List<Person>>> byGroupSize = Entry.comparingByValue(Comparator.comparingInt(List::size));
Comparator<Entry<Integer, List<Person>>> byAge = Entry.comparingByKey();
List<Entry<Integer, List<Person>>> entries = new ArrayList<>(intermediateGrouping.entrySet());
entries.sort(byGroupSize.reversed().thenComparing(byAge.reversed()));
List<List<Person>> result = new ArrayList<>(entries.size());
for (Entry<Integer, List<Person>> entry : entries) {
result.add(entry.getValue());
}
return result;
}
add a comment |
Since you were also looking for a non-stream solution:
public static Map<Integer, List<Person>> group(List<Person> people) {
Map<Integer, List<Person>> intermediateGrouping = new HashMap<>();
for (Person person : people) {
intermediateGrouping.computeIfAbsent(person.getAge(), k -> new ArrayList<>()).add(person);
}
Comparator<Entry<Integer, List<Person>>> byGroupSize = Entry.comparingByValue(Comparator.comparingInt(List::size));
Comparator<Entry<Integer, List<Person>>> byAge = Entry.comparingByKey();
List<Entry<Integer, List<Person>>> entries = new ArrayList<>(intermediateGrouping.entrySet());
entries.sort(byGroupSize.reversed().thenComparing(byAge.reversed()));
Map<Integer, List<Person>> result = new LinkedHashMap<>(entries.size());
for (Entry<Integer, List<Person>> entry : entries) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
Or if you prefer the result to be a List<List<Person>>
:
public static List<List<Person>> group(List<Person> people) {
Map<Integer, List<Person>> intermediateGrouping = new HashMap<>();
for (Person person : people) {
intermediateGrouping.computeIfAbsent(person.getAge(), k -> new ArrayList<>()).add(person);
}
Comparator<Entry<Integer, List<Person>>> byGroupSize = Entry.comparingByValue(Comparator.comparingInt(List::size));
Comparator<Entry<Integer, List<Person>>> byAge = Entry.comparingByKey();
List<Entry<Integer, List<Person>>> entries = new ArrayList<>(intermediateGrouping.entrySet());
entries.sort(byGroupSize.reversed().thenComparing(byAge.reversed()));
List<List<Person>> result = new ArrayList<>(entries.size());
for (Entry<Integer, List<Person>> entry : entries) {
result.add(entry.getValue());
}
return result;
}
Since you were also looking for a non-stream solution:
public static Map<Integer, List<Person>> group(List<Person> people) {
Map<Integer, List<Person>> intermediateGrouping = new HashMap<>();
for (Person person : people) {
intermediateGrouping.computeIfAbsent(person.getAge(), k -> new ArrayList<>()).add(person);
}
Comparator<Entry<Integer, List<Person>>> byGroupSize = Entry.comparingByValue(Comparator.comparingInt(List::size));
Comparator<Entry<Integer, List<Person>>> byAge = Entry.comparingByKey();
List<Entry<Integer, List<Person>>> entries = new ArrayList<>(intermediateGrouping.entrySet());
entries.sort(byGroupSize.reversed().thenComparing(byAge.reversed()));
Map<Integer, List<Person>> result = new LinkedHashMap<>(entries.size());
for (Entry<Integer, List<Person>> entry : entries) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
Or if you prefer the result to be a List<List<Person>>
:
public static List<List<Person>> group(List<Person> people) {
Map<Integer, List<Person>> intermediateGrouping = new HashMap<>();
for (Person person : people) {
intermediateGrouping.computeIfAbsent(person.getAge(), k -> new ArrayList<>()).add(person);
}
Comparator<Entry<Integer, List<Person>>> byGroupSize = Entry.comparingByValue(Comparator.comparingInt(List::size));
Comparator<Entry<Integer, List<Person>>> byAge = Entry.comparingByKey();
List<Entry<Integer, List<Person>>> entries = new ArrayList<>(intermediateGrouping.entrySet());
entries.sort(byGroupSize.reversed().thenComparing(byAge.reversed()));
List<List<Person>> result = new ArrayList<>(entries.size());
for (Entry<Integer, List<Person>> entry : entries) {
result.add(entry.getValue());
}
return result;
}
answered Nov 19 '18 at 13:32
Slaw
6,6992931
6,6992931
add a comment |
add a comment |
Try modifiying your sort comparator using the below implementation when the sizes are equal for a no streams approach
Collections.sort(entries, new Comparator<Map.Entry<Integer, List<Person>>>()
{
@Override
public int compare(Map.Entry<Integer, List<Person>> o1, Map.Entry<Integer, List<Person>> o2)
{
if(o1.getValue().size()<o2.getValue().size())
return 1;
else if(o1.getValue().size()>o2.getValue().size())
return -1;
else {
if( o1.getKey()< o2.getKey())
return 1;
else if(o1.getKey()>o2.getKey())
return -1;
else
return 0;
}
}
});
Let me know if it works on all your Test Cases
add a comment |
Try modifiying your sort comparator using the below implementation when the sizes are equal for a no streams approach
Collections.sort(entries, new Comparator<Map.Entry<Integer, List<Person>>>()
{
@Override
public int compare(Map.Entry<Integer, List<Person>> o1, Map.Entry<Integer, List<Person>> o2)
{
if(o1.getValue().size()<o2.getValue().size())
return 1;
else if(o1.getValue().size()>o2.getValue().size())
return -1;
else {
if( o1.getKey()< o2.getKey())
return 1;
else if(o1.getKey()>o2.getKey())
return -1;
else
return 0;
}
}
});
Let me know if it works on all your Test Cases
add a comment |
Try modifiying your sort comparator using the below implementation when the sizes are equal for a no streams approach
Collections.sort(entries, new Comparator<Map.Entry<Integer, List<Person>>>()
{
@Override
public int compare(Map.Entry<Integer, List<Person>> o1, Map.Entry<Integer, List<Person>> o2)
{
if(o1.getValue().size()<o2.getValue().size())
return 1;
else if(o1.getValue().size()>o2.getValue().size())
return -1;
else {
if( o1.getKey()< o2.getKey())
return 1;
else if(o1.getKey()>o2.getKey())
return -1;
else
return 0;
}
}
});
Let me know if it works on all your Test Cases
Try modifiying your sort comparator using the below implementation when the sizes are equal for a no streams approach
Collections.sort(entries, new Comparator<Map.Entry<Integer, List<Person>>>()
{
@Override
public int compare(Map.Entry<Integer, List<Person>> o1, Map.Entry<Integer, List<Person>> o2)
{
if(o1.getValue().size()<o2.getValue().size())
return 1;
else if(o1.getValue().size()>o2.getValue().size())
return -1;
else {
if( o1.getKey()< o2.getKey())
return 1;
else if(o1.getKey()>o2.getKey())
return -1;
else
return 0;
}
}
});
Let me know if it works on all your Test Cases
answered Nov 19 '18 at 13:29


Renny
608
608
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53375009%2fgrouping-and-double-sorting-listperson%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown