Java 8 lambda filtering based on condition as well as order
up vote
16
down vote
favorite
I was trying to filter a list based on multiple conditions, sorting.
class Student{
private int Age;
private String className;
private String Name;
public Student(int age, String className, String name) {
Age = age;
this.className = className;
Name = name;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
Now if I have a list of that, say
List<Student> students = new ArrayList<>();
students.add(new Student(24, "A", "Smith"));
students.add(new Student(24, "A", "John"));
students.add(new Student(30, "A", "John"));
students.add(new Student(20, "B", "John"));
students.add(new Student(24, "B", "Prince"));
How would I be able to get a list of the oldest students with a distinct name?
In C# this would be quite simple by using System.Linq GroupBy then comparing and then flattening with select, I'm not too sure how I could achieve the same in Java.
java lambda java-8 java-stream
add a comment |
up vote
16
down vote
favorite
I was trying to filter a list based on multiple conditions, sorting.
class Student{
private int Age;
private String className;
private String Name;
public Student(int age, String className, String name) {
Age = age;
this.className = className;
Name = name;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
Now if I have a list of that, say
List<Student> students = new ArrayList<>();
students.add(new Student(24, "A", "Smith"));
students.add(new Student(24, "A", "John"));
students.add(new Student(30, "A", "John"));
students.add(new Student(20, "B", "John"));
students.add(new Student(24, "B", "Prince"));
How would I be able to get a list of the oldest students with a distinct name?
In C# this would be quite simple by using System.Linq GroupBy then comparing and then flattening with select, I'm not too sure how I could achieve the same in Java.
java lambda java-8 java-stream
7
students.stream().collect(groupingBy(...))
.
– Andy Turner
Dec 5 at 14:56
Do you only want a list of the oldest and only the oldest ones?
– michaeak
Dec 5 at 15:07
Please tell what is the desired result. I.e. How the map/list/whatever looks like.
– michaeak
Dec 5 at 15:38
add a comment |
up vote
16
down vote
favorite
up vote
16
down vote
favorite
I was trying to filter a list based on multiple conditions, sorting.
class Student{
private int Age;
private String className;
private String Name;
public Student(int age, String className, String name) {
Age = age;
this.className = className;
Name = name;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
Now if I have a list of that, say
List<Student> students = new ArrayList<>();
students.add(new Student(24, "A", "Smith"));
students.add(new Student(24, "A", "John"));
students.add(new Student(30, "A", "John"));
students.add(new Student(20, "B", "John"));
students.add(new Student(24, "B", "Prince"));
How would I be able to get a list of the oldest students with a distinct name?
In C# this would be quite simple by using System.Linq GroupBy then comparing and then flattening with select, I'm not too sure how I could achieve the same in Java.
java lambda java-8 java-stream
I was trying to filter a list based on multiple conditions, sorting.
class Student{
private int Age;
private String className;
private String Name;
public Student(int age, String className, String name) {
Age = age;
this.className = className;
Name = name;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
Now if I have a list of that, say
List<Student> students = new ArrayList<>();
students.add(new Student(24, "A", "Smith"));
students.add(new Student(24, "A", "John"));
students.add(new Student(30, "A", "John"));
students.add(new Student(20, "B", "John"));
students.add(new Student(24, "B", "Prince"));
How would I be able to get a list of the oldest students with a distinct name?
In C# this would be quite simple by using System.Linq GroupBy then comparing and then flattening with select, I'm not too sure how I could achieve the same in Java.
java lambda java-8 java-stream
java lambda java-8 java-stream
asked Dec 5 at 14:55
The 0bserver
17710
17710
7
students.stream().collect(groupingBy(...))
.
– Andy Turner
Dec 5 at 14:56
Do you only want a list of the oldest and only the oldest ones?
– michaeak
Dec 5 at 15:07
Please tell what is the desired result. I.e. How the map/list/whatever looks like.
– michaeak
Dec 5 at 15:38
add a comment |
7
students.stream().collect(groupingBy(...))
.
– Andy Turner
Dec 5 at 14:56
Do you only want a list of the oldest and only the oldest ones?
– michaeak
Dec 5 at 15:07
Please tell what is the desired result. I.e. How the map/list/whatever looks like.
– michaeak
Dec 5 at 15:38
7
7
students.stream().collect(groupingBy(...))
.– Andy Turner
Dec 5 at 14:56
students.stream().collect(groupingBy(...))
.– Andy Turner
Dec 5 at 14:56
Do you only want a list of the oldest and only the oldest ones?
– michaeak
Dec 5 at 15:07
Do you only want a list of the oldest and only the oldest ones?
– michaeak
Dec 5 at 15:07
Please tell what is the desired result. I.e. How the map/list/whatever looks like.
– michaeak
Dec 5 at 15:38
Please tell what is the desired result. I.e. How the map/list/whatever looks like.
– michaeak
Dec 5 at 15:38
add a comment |
4 Answers
4
active
oldest
votes
up vote
15
down vote
Use the toMap
collector:
Collection<Student> values = students.stream()
.collect(toMap(Student::getName,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))))
.values();
Explanation
We're using this overload of toMap
:
toMap(Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
Student::getName
above is thekeyMapper
function used to extract the values for the map keys.
Function.identity()
above is thevalueMapper
function used to extract the values for the map values whereFunction.identity()
simply returns the elements in the source them selves i.e. theStudent
objects.
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))
above is the merge function used to "decide which Student object to return in the case of a key collission i.e. when two given students have the same name" in this case taking the oldestStudent
.- Finally, invoking
values()
returns us a collection of students.
The equivalent C# code being:
var values = students.GroupBy(s => s.Name, v => v,
(a, b) => b.OrderByDescending(e => e.Age).Take(1))
.SelectMany(x => x);
Explanation (for those unfamiliar with .NET)
We're using this extension method of GroupBy
:
System.Collections.Generic.IEnumerable<TResult> GroupBy<TSource,TKey,TElement,TResult>
(this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector,
Func<TSource,TElement> elementSelector,
Func<TKey,System.Collections.Generic.IEnumerable<TElement>,TResult> resultSelector);
s => s.Name
above is thekeySelector
function used to extract the value to group by.
v => v
above is theelementSelector
function used to extract the values i.e. theStudent
objects them selves.
b.OrderByDescending(e => e.Age).Take(1)
above is theresultSelector
which given anIEnumerable<Student>
represented asb
takes the oldest student.- Finally, we apply
.SelectMany(x => x);
to collapse the resultingIEnumerable<IEnumerable<Student>>
into aIEnumerable<Student>
.
Nice answer. Just wanted to say that usingv -> v
instead ofFunction.identity()
would make the code more similar to the C# equivalent and so easier to compare.
– Luis G.
Dec 5 at 17:08
add a comment |
up vote
5
down vote
Or without streams:
Map<String, Student> map = new HashMap<>();
students.forEach(x -> map.merge(x.getName(), x, (oldV, newV) -> oldV.getAge() > newV.getAge() ? oldV : newV));
Collection<Student> max = map.values();
Thought of this while starting of from your initial suggestion, but then an additionalMap
here, but doesmap.merge
save us compared totoMap
?
– nullpointer
Dec 5 at 15:27
3
@nullpointer This should have been my answer (I'm supposedly thewithout streams guy
here), so I feel I can answer your question... Actually,Collectors.toMap
usesMap.merge
under the hood. It even says so in the docs:mergeFunction - a merge function, used to resolve collisions between values associated with the same key, as supplied to Map.merge(Object, Object, BiFunction)
.
– Federico Peralta Schaffner
Dec 5 at 15:45
add a comment |
up vote
1
down vote
If you need a grouping only sorted, it is quite simple:
Map<String, List<Student>> collect = students.stream() // stream capabilities
.sorted(Comparator.comparingInt(Student::getAge).reversed()) // sort by age, descending
.collect(Collectors.groupingBy(Student::getName)); // group by name.
Output in collect:
- Prince=[Student [Age=24, className=B, Name=Prince]],
- Smith=[Student [Age=24, className=A, Name=Smith]],
- John=[Student [Age=30, className=A, Name=John], Student [Age=24, className=A, Name=John], Student [Age=20, className=B, Name=John]]
add a comment |
up vote
1
down vote
Just to mix and merge the other solutions, you could alternatively do :
Map<String, Student> nameToStudentMap = new HashMap<>();
Set<Student> finalListOfStudents = students.stream()
.map(x -> nameToStudentMap.merge(x.getName(), x, (a, b) -> a.getAge() > b.getAge() ? a : b))
.collect(Collectors.toSet());
3
This violates the requirement of statelessness on the parameter ofStream.map
.
– Andy Turner
Dec 5 at 22:00
add a comment |
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
15
down vote
Use the toMap
collector:
Collection<Student> values = students.stream()
.collect(toMap(Student::getName,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))))
.values();
Explanation
We're using this overload of toMap
:
toMap(Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
Student::getName
above is thekeyMapper
function used to extract the values for the map keys.
Function.identity()
above is thevalueMapper
function used to extract the values for the map values whereFunction.identity()
simply returns the elements in the source them selves i.e. theStudent
objects.
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))
above is the merge function used to "decide which Student object to return in the case of a key collission i.e. when two given students have the same name" in this case taking the oldestStudent
.- Finally, invoking
values()
returns us a collection of students.
The equivalent C# code being:
var values = students.GroupBy(s => s.Name, v => v,
(a, b) => b.OrderByDescending(e => e.Age).Take(1))
.SelectMany(x => x);
Explanation (for those unfamiliar with .NET)
We're using this extension method of GroupBy
:
System.Collections.Generic.IEnumerable<TResult> GroupBy<TSource,TKey,TElement,TResult>
(this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector,
Func<TSource,TElement> elementSelector,
Func<TKey,System.Collections.Generic.IEnumerable<TElement>,TResult> resultSelector);
s => s.Name
above is thekeySelector
function used to extract the value to group by.
v => v
above is theelementSelector
function used to extract the values i.e. theStudent
objects them selves.
b.OrderByDescending(e => e.Age).Take(1)
above is theresultSelector
which given anIEnumerable<Student>
represented asb
takes the oldest student.- Finally, we apply
.SelectMany(x => x);
to collapse the resultingIEnumerable<IEnumerable<Student>>
into aIEnumerable<Student>
.
Nice answer. Just wanted to say that usingv -> v
instead ofFunction.identity()
would make the code more similar to the C# equivalent and so easier to compare.
– Luis G.
Dec 5 at 17:08
add a comment |
up vote
15
down vote
Use the toMap
collector:
Collection<Student> values = students.stream()
.collect(toMap(Student::getName,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))))
.values();
Explanation
We're using this overload of toMap
:
toMap(Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
Student::getName
above is thekeyMapper
function used to extract the values for the map keys.
Function.identity()
above is thevalueMapper
function used to extract the values for the map values whereFunction.identity()
simply returns the elements in the source them selves i.e. theStudent
objects.
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))
above is the merge function used to "decide which Student object to return in the case of a key collission i.e. when two given students have the same name" in this case taking the oldestStudent
.- Finally, invoking
values()
returns us a collection of students.
The equivalent C# code being:
var values = students.GroupBy(s => s.Name, v => v,
(a, b) => b.OrderByDescending(e => e.Age).Take(1))
.SelectMany(x => x);
Explanation (for those unfamiliar with .NET)
We're using this extension method of GroupBy
:
System.Collections.Generic.IEnumerable<TResult> GroupBy<TSource,TKey,TElement,TResult>
(this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector,
Func<TSource,TElement> elementSelector,
Func<TKey,System.Collections.Generic.IEnumerable<TElement>,TResult> resultSelector);
s => s.Name
above is thekeySelector
function used to extract the value to group by.
v => v
above is theelementSelector
function used to extract the values i.e. theStudent
objects them selves.
b.OrderByDescending(e => e.Age).Take(1)
above is theresultSelector
which given anIEnumerable<Student>
represented asb
takes the oldest student.- Finally, we apply
.SelectMany(x => x);
to collapse the resultingIEnumerable<IEnumerable<Student>>
into aIEnumerable<Student>
.
Nice answer. Just wanted to say that usingv -> v
instead ofFunction.identity()
would make the code more similar to the C# equivalent and so easier to compare.
– Luis G.
Dec 5 at 17:08
add a comment |
up vote
15
down vote
up vote
15
down vote
Use the toMap
collector:
Collection<Student> values = students.stream()
.collect(toMap(Student::getName,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))))
.values();
Explanation
We're using this overload of toMap
:
toMap(Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
Student::getName
above is thekeyMapper
function used to extract the values for the map keys.
Function.identity()
above is thevalueMapper
function used to extract the values for the map values whereFunction.identity()
simply returns the elements in the source them selves i.e. theStudent
objects.
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))
above is the merge function used to "decide which Student object to return in the case of a key collission i.e. when two given students have the same name" in this case taking the oldestStudent
.- Finally, invoking
values()
returns us a collection of students.
The equivalent C# code being:
var values = students.GroupBy(s => s.Name, v => v,
(a, b) => b.OrderByDescending(e => e.Age).Take(1))
.SelectMany(x => x);
Explanation (for those unfamiliar with .NET)
We're using this extension method of GroupBy
:
System.Collections.Generic.IEnumerable<TResult> GroupBy<TSource,TKey,TElement,TResult>
(this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector,
Func<TSource,TElement> elementSelector,
Func<TKey,System.Collections.Generic.IEnumerable<TElement>,TResult> resultSelector);
s => s.Name
above is thekeySelector
function used to extract the value to group by.
v => v
above is theelementSelector
function used to extract the values i.e. theStudent
objects them selves.
b.OrderByDescending(e => e.Age).Take(1)
above is theresultSelector
which given anIEnumerable<Student>
represented asb
takes the oldest student.- Finally, we apply
.SelectMany(x => x);
to collapse the resultingIEnumerable<IEnumerable<Student>>
into aIEnumerable<Student>
.
Use the toMap
collector:
Collection<Student> values = students.stream()
.collect(toMap(Student::getName,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))))
.values();
Explanation
We're using this overload of toMap
:
toMap(Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
Student::getName
above is thekeyMapper
function used to extract the values for the map keys.
Function.identity()
above is thevalueMapper
function used to extract the values for the map values whereFunction.identity()
simply returns the elements in the source them selves i.e. theStudent
objects.
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))
above is the merge function used to "decide which Student object to return in the case of a key collission i.e. when two given students have the same name" in this case taking the oldestStudent
.- Finally, invoking
values()
returns us a collection of students.
The equivalent C# code being:
var values = students.GroupBy(s => s.Name, v => v,
(a, b) => b.OrderByDescending(e => e.Age).Take(1))
.SelectMany(x => x);
Explanation (for those unfamiliar with .NET)
We're using this extension method of GroupBy
:
System.Collections.Generic.IEnumerable<TResult> GroupBy<TSource,TKey,TElement,TResult>
(this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector,
Func<TSource,TElement> elementSelector,
Func<TKey,System.Collections.Generic.IEnumerable<TElement>,TResult> resultSelector);
s => s.Name
above is thekeySelector
function used to extract the value to group by.
v => v
above is theelementSelector
function used to extract the values i.e. theStudent
objects them selves.
b.OrderByDescending(e => e.Age).Take(1)
above is theresultSelector
which given anIEnumerable<Student>
represented asb
takes the oldest student.- Finally, we apply
.SelectMany(x => x);
to collapse the resultingIEnumerable<IEnumerable<Student>>
into aIEnumerable<Student>
.
edited Dec 5 at 15:37
answered Dec 5 at 14:56
Aomine
35.8k62960
35.8k62960
Nice answer. Just wanted to say that usingv -> v
instead ofFunction.identity()
would make the code more similar to the C# equivalent and so easier to compare.
– Luis G.
Dec 5 at 17:08
add a comment |
Nice answer. Just wanted to say that usingv -> v
instead ofFunction.identity()
would make the code more similar to the C# equivalent and so easier to compare.
– Luis G.
Dec 5 at 17:08
Nice answer. Just wanted to say that using
v -> v
instead of Function.identity()
would make the code more similar to the C# equivalent and so easier to compare.– Luis G.
Dec 5 at 17:08
Nice answer. Just wanted to say that using
v -> v
instead of Function.identity()
would make the code more similar to the C# equivalent and so easier to compare.– Luis G.
Dec 5 at 17:08
add a comment |
up vote
5
down vote
Or without streams:
Map<String, Student> map = new HashMap<>();
students.forEach(x -> map.merge(x.getName(), x, (oldV, newV) -> oldV.getAge() > newV.getAge() ? oldV : newV));
Collection<Student> max = map.values();
Thought of this while starting of from your initial suggestion, but then an additionalMap
here, but doesmap.merge
save us compared totoMap
?
– nullpointer
Dec 5 at 15:27
3
@nullpointer This should have been my answer (I'm supposedly thewithout streams guy
here), so I feel I can answer your question... Actually,Collectors.toMap
usesMap.merge
under the hood. It even says so in the docs:mergeFunction - a merge function, used to resolve collisions between values associated with the same key, as supplied to Map.merge(Object, Object, BiFunction)
.
– Federico Peralta Schaffner
Dec 5 at 15:45
add a comment |
up vote
5
down vote
Or without streams:
Map<String, Student> map = new HashMap<>();
students.forEach(x -> map.merge(x.getName(), x, (oldV, newV) -> oldV.getAge() > newV.getAge() ? oldV : newV));
Collection<Student> max = map.values();
Thought of this while starting of from your initial suggestion, but then an additionalMap
here, but doesmap.merge
save us compared totoMap
?
– nullpointer
Dec 5 at 15:27
3
@nullpointer This should have been my answer (I'm supposedly thewithout streams guy
here), so I feel I can answer your question... Actually,Collectors.toMap
usesMap.merge
under the hood. It even says so in the docs:mergeFunction - a merge function, used to resolve collisions between values associated with the same key, as supplied to Map.merge(Object, Object, BiFunction)
.
– Federico Peralta Schaffner
Dec 5 at 15:45
add a comment |
up vote
5
down vote
up vote
5
down vote
Or without streams:
Map<String, Student> map = new HashMap<>();
students.forEach(x -> map.merge(x.getName(), x, (oldV, newV) -> oldV.getAge() > newV.getAge() ? oldV : newV));
Collection<Student> max = map.values();
Or without streams:
Map<String, Student> map = new HashMap<>();
students.forEach(x -> map.merge(x.getName(), x, (oldV, newV) -> oldV.getAge() > newV.getAge() ? oldV : newV));
Collection<Student> max = map.values();
edited Dec 5 at 15:18
answered Dec 5 at 15:09
Eugene
67.6k997160
67.6k997160
Thought of this while starting of from your initial suggestion, but then an additionalMap
here, but doesmap.merge
save us compared totoMap
?
– nullpointer
Dec 5 at 15:27
3
@nullpointer This should have been my answer (I'm supposedly thewithout streams guy
here), so I feel I can answer your question... Actually,Collectors.toMap
usesMap.merge
under the hood. It even says so in the docs:mergeFunction - a merge function, used to resolve collisions between values associated with the same key, as supplied to Map.merge(Object, Object, BiFunction)
.
– Federico Peralta Schaffner
Dec 5 at 15:45
add a comment |
Thought of this while starting of from your initial suggestion, but then an additionalMap
here, but doesmap.merge
save us compared totoMap
?
– nullpointer
Dec 5 at 15:27
3
@nullpointer This should have been my answer (I'm supposedly thewithout streams guy
here), so I feel I can answer your question... Actually,Collectors.toMap
usesMap.merge
under the hood. It even says so in the docs:mergeFunction - a merge function, used to resolve collisions between values associated with the same key, as supplied to Map.merge(Object, Object, BiFunction)
.
– Federico Peralta Schaffner
Dec 5 at 15:45
Thought of this while starting of from your initial suggestion, but then an additional
Map
here, but does map.merge
save us compared to toMap
?– nullpointer
Dec 5 at 15:27
Thought of this while starting of from your initial suggestion, but then an additional
Map
here, but does map.merge
save us compared to toMap
?– nullpointer
Dec 5 at 15:27
3
3
@nullpointer This should have been my answer (I'm supposedly the
without streams guy
here), so I feel I can answer your question... Actually, Collectors.toMap
uses Map.merge
under the hood. It even says so in the docs: mergeFunction - a merge function, used to resolve collisions between values associated with the same key, as supplied to Map.merge(Object, Object, BiFunction)
.– Federico Peralta Schaffner
Dec 5 at 15:45
@nullpointer This should have been my answer (I'm supposedly the
without streams guy
here), so I feel I can answer your question... Actually, Collectors.toMap
uses Map.merge
under the hood. It even says so in the docs: mergeFunction - a merge function, used to resolve collisions between values associated with the same key, as supplied to Map.merge(Object, Object, BiFunction)
.– Federico Peralta Schaffner
Dec 5 at 15:45
add a comment |
up vote
1
down vote
If you need a grouping only sorted, it is quite simple:
Map<String, List<Student>> collect = students.stream() // stream capabilities
.sorted(Comparator.comparingInt(Student::getAge).reversed()) // sort by age, descending
.collect(Collectors.groupingBy(Student::getName)); // group by name.
Output in collect:
- Prince=[Student [Age=24, className=B, Name=Prince]],
- Smith=[Student [Age=24, className=A, Name=Smith]],
- John=[Student [Age=30, className=A, Name=John], Student [Age=24, className=A, Name=John], Student [Age=20, className=B, Name=John]]
add a comment |
up vote
1
down vote
If you need a grouping only sorted, it is quite simple:
Map<String, List<Student>> collect = students.stream() // stream capabilities
.sorted(Comparator.comparingInt(Student::getAge).reversed()) // sort by age, descending
.collect(Collectors.groupingBy(Student::getName)); // group by name.
Output in collect:
- Prince=[Student [Age=24, className=B, Name=Prince]],
- Smith=[Student [Age=24, className=A, Name=Smith]],
- John=[Student [Age=30, className=A, Name=John], Student [Age=24, className=A, Name=John], Student [Age=20, className=B, Name=John]]
add a comment |
up vote
1
down vote
up vote
1
down vote
If you need a grouping only sorted, it is quite simple:
Map<String, List<Student>> collect = students.stream() // stream capabilities
.sorted(Comparator.comparingInt(Student::getAge).reversed()) // sort by age, descending
.collect(Collectors.groupingBy(Student::getName)); // group by name.
Output in collect:
- Prince=[Student [Age=24, className=B, Name=Prince]],
- Smith=[Student [Age=24, className=A, Name=Smith]],
- John=[Student [Age=30, className=A, Name=John], Student [Age=24, className=A, Name=John], Student [Age=20, className=B, Name=John]]
If you need a grouping only sorted, it is quite simple:
Map<String, List<Student>> collect = students.stream() // stream capabilities
.sorted(Comparator.comparingInt(Student::getAge).reversed()) // sort by age, descending
.collect(Collectors.groupingBy(Student::getName)); // group by name.
Output in collect:
- Prince=[Student [Age=24, className=B, Name=Prince]],
- Smith=[Student [Age=24, className=A, Name=Smith]],
- John=[Student [Age=30, className=A, Name=John], Student [Age=24, className=A, Name=John], Student [Age=20, className=B, Name=John]]
edited Dec 5 at 15:45
answered Dec 5 at 14:57
michaeak
739315
739315
add a comment |
add a comment |
up vote
1
down vote
Just to mix and merge the other solutions, you could alternatively do :
Map<String, Student> nameToStudentMap = new HashMap<>();
Set<Student> finalListOfStudents = students.stream()
.map(x -> nameToStudentMap.merge(x.getName(), x, (a, b) -> a.getAge() > b.getAge() ? a : b))
.collect(Collectors.toSet());
3
This violates the requirement of statelessness on the parameter ofStream.map
.
– Andy Turner
Dec 5 at 22:00
add a comment |
up vote
1
down vote
Just to mix and merge the other solutions, you could alternatively do :
Map<String, Student> nameToStudentMap = new HashMap<>();
Set<Student> finalListOfStudents = students.stream()
.map(x -> nameToStudentMap.merge(x.getName(), x, (a, b) -> a.getAge() > b.getAge() ? a : b))
.collect(Collectors.toSet());
3
This violates the requirement of statelessness on the parameter ofStream.map
.
– Andy Turner
Dec 5 at 22:00
add a comment |
up vote
1
down vote
up vote
1
down vote
Just to mix and merge the other solutions, you could alternatively do :
Map<String, Student> nameToStudentMap = new HashMap<>();
Set<Student> finalListOfStudents = students.stream()
.map(x -> nameToStudentMap.merge(x.getName(), x, (a, b) -> a.getAge() > b.getAge() ? a : b))
.collect(Collectors.toSet());
Just to mix and merge the other solutions, you could alternatively do :
Map<String, Student> nameToStudentMap = new HashMap<>();
Set<Student> finalListOfStudents = students.stream()
.map(x -> nameToStudentMap.merge(x.getName(), x, (a, b) -> a.getAge() > b.getAge() ? a : b))
.collect(Collectors.toSet());
edited Dec 5 at 16:17
answered Dec 5 at 16:08
nullpointer
38.2k1073146
38.2k1073146
3
This violates the requirement of statelessness on the parameter ofStream.map
.
– Andy Turner
Dec 5 at 22:00
add a comment |
3
This violates the requirement of statelessness on the parameter ofStream.map
.
– Andy Turner
Dec 5 at 22:00
3
3
This violates the requirement of statelessness on the parameter of
Stream.map
.– Andy Turner
Dec 5 at 22:00
This violates the requirement of statelessness on the parameter of
Stream.map
.– Andy Turner
Dec 5 at 22:00
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%2f53635022%2fjava-8-lambda-filtering-based-on-condition-as-well-as-order%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
7
students.stream().collect(groupingBy(...))
.– Andy Turner
Dec 5 at 14:56
Do you only want a list of the oldest and only the oldest ones?
– michaeak
Dec 5 at 15:07
Please tell what is the desired result. I.e. How the map/list/whatever looks like.
– michaeak
Dec 5 at 15:38