Using Java 8 stream methods to get the last max value

Multi tool use
Given a list of items with properties, I am trying to get the last item to appear with a maximum value of said property.
For example, for the following list of objects:
t i
A: 3
D: 7 *
F: 4
C: 5
X: 7 *
M: 6
I can get one of the Things with the highest i
:
Thing t = items.stream()
.max(Comparator.comparingLong(Thing::getI))
.orElse(null);
However, this will get me Thing t = D
. Is there a clean and elegant way of getting the last item, i.e. X
in this case?
One possible solution is using the reduce
function. However, the property is calculated on the fly and it would look more like:
Thing t = items.stream()
.reduce((left, right) -> {
long leftValue = valueFunction.apply(left);
long rightValue = valueFunction.apply(right);
return leftValue > rightValue ? left : right;
})
.orElse(null);
The valueFunction
now needs to be called nearly twice as often.
Other obvious roundabout solutions are:
- Store the object in a Tuple with its index
- Store the object in a Tuple with its computed value
- Reverse the list beforehand
- Don't use Streams
java java-8 java-stream
add a comment |
Given a list of items with properties, I am trying to get the last item to appear with a maximum value of said property.
For example, for the following list of objects:
t i
A: 3
D: 7 *
F: 4
C: 5
X: 7 *
M: 6
I can get one of the Things with the highest i
:
Thing t = items.stream()
.max(Comparator.comparingLong(Thing::getI))
.orElse(null);
However, this will get me Thing t = D
. Is there a clean and elegant way of getting the last item, i.e. X
in this case?
One possible solution is using the reduce
function. However, the property is calculated on the fly and it would look more like:
Thing t = items.stream()
.reduce((left, right) -> {
long leftValue = valueFunction.apply(left);
long rightValue = valueFunction.apply(right);
return leftValue > rightValue ? left : right;
})
.orElse(null);
The valueFunction
now needs to be called nearly twice as often.
Other obvious roundabout solutions are:
- Store the object in a Tuple with its index
- Store the object in a Tuple with its computed value
- Reverse the list beforehand
- Don't use Streams
java java-8 java-stream
add a comment |
Given a list of items with properties, I am trying to get the last item to appear with a maximum value of said property.
For example, for the following list of objects:
t i
A: 3
D: 7 *
F: 4
C: 5
X: 7 *
M: 6
I can get one of the Things with the highest i
:
Thing t = items.stream()
.max(Comparator.comparingLong(Thing::getI))
.orElse(null);
However, this will get me Thing t = D
. Is there a clean and elegant way of getting the last item, i.e. X
in this case?
One possible solution is using the reduce
function. However, the property is calculated on the fly and it would look more like:
Thing t = items.stream()
.reduce((left, right) -> {
long leftValue = valueFunction.apply(left);
long rightValue = valueFunction.apply(right);
return leftValue > rightValue ? left : right;
})
.orElse(null);
The valueFunction
now needs to be called nearly twice as often.
Other obvious roundabout solutions are:
- Store the object in a Tuple with its index
- Store the object in a Tuple with its computed value
- Reverse the list beforehand
- Don't use Streams
java java-8 java-stream
Given a list of items with properties, I am trying to get the last item to appear with a maximum value of said property.
For example, for the following list of objects:
t i
A: 3
D: 7 *
F: 4
C: 5
X: 7 *
M: 6
I can get one of the Things with the highest i
:
Thing t = items.stream()
.max(Comparator.comparingLong(Thing::getI))
.orElse(null);
However, this will get me Thing t = D
. Is there a clean and elegant way of getting the last item, i.e. X
in this case?
One possible solution is using the reduce
function. However, the property is calculated on the fly and it would look more like:
Thing t = items.stream()
.reduce((left, right) -> {
long leftValue = valueFunction.apply(left);
long rightValue = valueFunction.apply(right);
return leftValue > rightValue ? left : right;
})
.orElse(null);
The valueFunction
now needs to be called nearly twice as often.
Other obvious roundabout solutions are:
- Store the object in a Tuple with its index
- Store the object in a Tuple with its computed value
- Reverse the list beforehand
- Don't use Streams
java java-8 java-stream
java java-8 java-stream
edited 53 mins ago


nullpointer
47.5k11100191
47.5k11100191
asked 1 hour ago
DrucklesDruckles
88211032
88211032
add a comment |
add a comment |
6 Answers
6
active
oldest
votes
Conceptually, you seem to be possibly looking for something like thenComparing
using the index
of the elements in the list:
Thing t = items.stream()
.max(Comparator.comparingLong(Thing::getI).thenComparing(items::indexOf))
.orElse(null);
1
Assuming: that for two objects if attributeI
is equal that doesn't mean the objects are equal as well. In which case theindexOf
would return same value always.
– nullpointer
54 mins ago
1
I like this. 1+
– Eugene
35 mins ago
add a comment |
To avoid the multiple applications of valueFunction in your reduce solution, simply explicitly calculate the result and put it in a tuple:
Item lastMax = items.stream()
.map(item -> new AbstractMap.SimpleEntry<Item, Long>(item, valueFunction.apply(item)))
.reduce((l, r) -> l.getValue() > r.getValue() ? l : r )
.map(Map.Entry::getKey)
.orElse(null);
add a comment |
Remove the equals option from the comparator (ie. write your own comparator that doesn't include an equals option):
Thing t = items.stream()
.max((a, b) -> a.getI() > b.getI() ? 1 : -1)
.orElse(null);
add a comment |
Your current implementation using reduce
looks good, unless your value-extractor function is costly.
Considering later you may want to reuse the logic for different object types & fields, I would extract the logic itself in separate generic method/methods:
public static <T, K, V> Function<T, Map.Entry<K, V>> toEntry(Function<T, K> keyFunc, Function<T, V> valueFunc){
return t -> new AbstractMap.SimpleEntry<>(keyFunc.apply(t), valueFunc.apply(t));
}
public static <ITEM, FIELD extends Comparable<FIELD>> ITEM maxBy(Function<ITEM, FIELD> extractor, Collection<ITEM> items) {
return items.stream()
.map(toEntry(identity(), extractor))
.max(comparing(Map.Entry::getValue))
.map(Map.Entry::getKey)
.orElse(null);
}
The code snippets above can be used like this:
Thing maxThing = maxBy(Thing::getField, things);
AnotherThing maxAnotherThing = maxBy(AnotherThing::getAnotherField, anotherThings);
add a comment |
You can still use the reduction to get this thing done. If t1 is larger, then only it will keep t1. In all the other cases it will keep t2. If either t2 is larger or t1 and t2 are the same, then it will eventually return t2 adhering to your requirement.
Thing t = items.stream().
reduce((t1, t2) -> t1.getI() > t2.getI() ? t1 : t2)
.orElse(null);
There is not
orgetT()
in this case, it's simply used as a label in this example. And it can't be used to order the Stream; it's the order of the items in the original list that is important.
– Druckles
1 hour ago
add a comment |
Stream is not necessary bad if you do things in two steps :
1) Find the i
value that has more occurrences in the Iterable
(as you did)
2) Search the last element for this i
value by starting from the end of items:
Thing t =
items.stream()
.max(Comparator.comparingLong(Thing::getI))
.mapping(firstMaxThing ->
ListIterator li = items.listIterator(items.size());
while(li.hasPrevious()) {
Thing current = li.previous()
if (li.previous().getI() == firstMaxThing.getI()){
return current;
}
}
throw new RuntimeException("should not occur here if max was found");
).orElse(null)
We could write it with StreamSupport
to make it more elegant :
Thing t =
items.stream()
.max(Comparator.comparingLong(Thing::getI))
.mapping(firstMaxThing ->
Iterable<Thing> iterable = () -> items.listIterator(items.size());
return
StreamSupport.stream(iterable.spliterator(), false)
.filter(i -> i.getI() == firstMaxThing.getI())
.findFirst().get(); // here get() cannot fail as *max()* returned something.
)
.orElse(null)
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%2f54535632%2fusing-java-8-stream-methods-to-get-the-last-max-value%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
Conceptually, you seem to be possibly looking for something like thenComparing
using the index
of the elements in the list:
Thing t = items.stream()
.max(Comparator.comparingLong(Thing::getI).thenComparing(items::indexOf))
.orElse(null);
1
Assuming: that for two objects if attributeI
is equal that doesn't mean the objects are equal as well. In which case theindexOf
would return same value always.
– nullpointer
54 mins ago
1
I like this. 1+
– Eugene
35 mins ago
add a comment |
Conceptually, you seem to be possibly looking for something like thenComparing
using the index
of the elements in the list:
Thing t = items.stream()
.max(Comparator.comparingLong(Thing::getI).thenComparing(items::indexOf))
.orElse(null);
1
Assuming: that for two objects if attributeI
is equal that doesn't mean the objects are equal as well. In which case theindexOf
would return same value always.
– nullpointer
54 mins ago
1
I like this. 1+
– Eugene
35 mins ago
add a comment |
Conceptually, you seem to be possibly looking for something like thenComparing
using the index
of the elements in the list:
Thing t = items.stream()
.max(Comparator.comparingLong(Thing::getI).thenComparing(items::indexOf))
.orElse(null);
Conceptually, you seem to be possibly looking for something like thenComparing
using the index
of the elements in the list:
Thing t = items.stream()
.max(Comparator.comparingLong(Thing::getI).thenComparing(items::indexOf))
.orElse(null);
edited 35 mins ago
answered 57 mins ago


nullpointernullpointer
47.5k11100191
47.5k11100191
1
Assuming: that for two objects if attributeI
is equal that doesn't mean the objects are equal as well. In which case theindexOf
would return same value always.
– nullpointer
54 mins ago
1
I like this. 1+
– Eugene
35 mins ago
add a comment |
1
Assuming: that for two objects if attributeI
is equal that doesn't mean the objects are equal as well. In which case theindexOf
would return same value always.
– nullpointer
54 mins ago
1
I like this. 1+
– Eugene
35 mins ago
1
1
Assuming: that for two objects if attribute
I
is equal that doesn't mean the objects are equal as well. In which case the indexOf
would return same value always.– nullpointer
54 mins ago
Assuming: that for two objects if attribute
I
is equal that doesn't mean the objects are equal as well. In which case the indexOf
would return same value always.– nullpointer
54 mins ago
1
1
I like this. 1+
– Eugene
35 mins ago
I like this. 1+
– Eugene
35 mins ago
add a comment |
To avoid the multiple applications of valueFunction in your reduce solution, simply explicitly calculate the result and put it in a tuple:
Item lastMax = items.stream()
.map(item -> new AbstractMap.SimpleEntry<Item, Long>(item, valueFunction.apply(item)))
.reduce((l, r) -> l.getValue() > r.getValue() ? l : r )
.map(Map.Entry::getKey)
.orElse(null);
add a comment |
To avoid the multiple applications of valueFunction in your reduce solution, simply explicitly calculate the result and put it in a tuple:
Item lastMax = items.stream()
.map(item -> new AbstractMap.SimpleEntry<Item, Long>(item, valueFunction.apply(item)))
.reduce((l, r) -> l.getValue() > r.getValue() ? l : r )
.map(Map.Entry::getKey)
.orElse(null);
add a comment |
To avoid the multiple applications of valueFunction in your reduce solution, simply explicitly calculate the result and put it in a tuple:
Item lastMax = items.stream()
.map(item -> new AbstractMap.SimpleEntry<Item, Long>(item, valueFunction.apply(item)))
.reduce((l, r) -> l.getValue() > r.getValue() ? l : r )
.map(Map.Entry::getKey)
.orElse(null);
To avoid the multiple applications of valueFunction in your reduce solution, simply explicitly calculate the result and put it in a tuple:
Item lastMax = items.stream()
.map(item -> new AbstractMap.SimpleEntry<Item, Long>(item, valueFunction.apply(item)))
.reduce((l, r) -> l.getValue() > r.getValue() ? l : r )
.map(Map.Entry::getKey)
.orElse(null);
answered 14 mins ago
MikeFHayMikeFHay
3,13032035
3,13032035
add a comment |
add a comment |
Remove the equals option from the comparator (ie. write your own comparator that doesn't include an equals option):
Thing t = items.stream()
.max((a, b) -> a.getI() > b.getI() ? 1 : -1)
.orElse(null);
add a comment |
Remove the equals option from the comparator (ie. write your own comparator that doesn't include an equals option):
Thing t = items.stream()
.max((a, b) -> a.getI() > b.getI() ? 1 : -1)
.orElse(null);
add a comment |
Remove the equals option from the comparator (ie. write your own comparator that doesn't include an equals option):
Thing t = items.stream()
.max((a, b) -> a.getI() > b.getI() ? 1 : -1)
.orElse(null);
Remove the equals option from the comparator (ie. write your own comparator that doesn't include an equals option):
Thing t = items.stream()
.max((a, b) -> a.getI() > b.getI() ? 1 : -1)
.orElse(null);
answered 1 hour ago
jvdmrjvdmr
1184
1184
add a comment |
add a comment |
Your current implementation using reduce
looks good, unless your value-extractor function is costly.
Considering later you may want to reuse the logic for different object types & fields, I would extract the logic itself in separate generic method/methods:
public static <T, K, V> Function<T, Map.Entry<K, V>> toEntry(Function<T, K> keyFunc, Function<T, V> valueFunc){
return t -> new AbstractMap.SimpleEntry<>(keyFunc.apply(t), valueFunc.apply(t));
}
public static <ITEM, FIELD extends Comparable<FIELD>> ITEM maxBy(Function<ITEM, FIELD> extractor, Collection<ITEM> items) {
return items.stream()
.map(toEntry(identity(), extractor))
.max(comparing(Map.Entry::getValue))
.map(Map.Entry::getKey)
.orElse(null);
}
The code snippets above can be used like this:
Thing maxThing = maxBy(Thing::getField, things);
AnotherThing maxAnotherThing = maxBy(AnotherThing::getAnotherField, anotherThings);
add a comment |
Your current implementation using reduce
looks good, unless your value-extractor function is costly.
Considering later you may want to reuse the logic for different object types & fields, I would extract the logic itself in separate generic method/methods:
public static <T, K, V> Function<T, Map.Entry<K, V>> toEntry(Function<T, K> keyFunc, Function<T, V> valueFunc){
return t -> new AbstractMap.SimpleEntry<>(keyFunc.apply(t), valueFunc.apply(t));
}
public static <ITEM, FIELD extends Comparable<FIELD>> ITEM maxBy(Function<ITEM, FIELD> extractor, Collection<ITEM> items) {
return items.stream()
.map(toEntry(identity(), extractor))
.max(comparing(Map.Entry::getValue))
.map(Map.Entry::getKey)
.orElse(null);
}
The code snippets above can be used like this:
Thing maxThing = maxBy(Thing::getField, things);
AnotherThing maxAnotherThing = maxBy(AnotherThing::getAnotherField, anotherThings);
add a comment |
Your current implementation using reduce
looks good, unless your value-extractor function is costly.
Considering later you may want to reuse the logic for different object types & fields, I would extract the logic itself in separate generic method/methods:
public static <T, K, V> Function<T, Map.Entry<K, V>> toEntry(Function<T, K> keyFunc, Function<T, V> valueFunc){
return t -> new AbstractMap.SimpleEntry<>(keyFunc.apply(t), valueFunc.apply(t));
}
public static <ITEM, FIELD extends Comparable<FIELD>> ITEM maxBy(Function<ITEM, FIELD> extractor, Collection<ITEM> items) {
return items.stream()
.map(toEntry(identity(), extractor))
.max(comparing(Map.Entry::getValue))
.map(Map.Entry::getKey)
.orElse(null);
}
The code snippets above can be used like this:
Thing maxThing = maxBy(Thing::getField, things);
AnotherThing maxAnotherThing = maxBy(AnotherThing::getAnotherField, anotherThings);
Your current implementation using reduce
looks good, unless your value-extractor function is costly.
Considering later you may want to reuse the logic for different object types & fields, I would extract the logic itself in separate generic method/methods:
public static <T, K, V> Function<T, Map.Entry<K, V>> toEntry(Function<T, K> keyFunc, Function<T, V> valueFunc){
return t -> new AbstractMap.SimpleEntry<>(keyFunc.apply(t), valueFunc.apply(t));
}
public static <ITEM, FIELD extends Comparable<FIELD>> ITEM maxBy(Function<ITEM, FIELD> extractor, Collection<ITEM> items) {
return items.stream()
.map(toEntry(identity(), extractor))
.max(comparing(Map.Entry::getValue))
.map(Map.Entry::getKey)
.orElse(null);
}
The code snippets above can be used like this:
Thing maxThing = maxBy(Thing::getField, things);
AnotherThing maxAnotherThing = maxBy(AnotherThing::getAnotherField, anotherThings);
answered 37 mins ago


ETOETO
2,432626
2,432626
add a comment |
add a comment |
You can still use the reduction to get this thing done. If t1 is larger, then only it will keep t1. In all the other cases it will keep t2. If either t2 is larger or t1 and t2 are the same, then it will eventually return t2 adhering to your requirement.
Thing t = items.stream().
reduce((t1, t2) -> t1.getI() > t2.getI() ? t1 : t2)
.orElse(null);
There is not
orgetT()
in this case, it's simply used as a label in this example. And it can't be used to order the Stream; it's the order of the items in the original list that is important.
– Druckles
1 hour ago
add a comment |
You can still use the reduction to get this thing done. If t1 is larger, then only it will keep t1. In all the other cases it will keep t2. If either t2 is larger or t1 and t2 are the same, then it will eventually return t2 adhering to your requirement.
Thing t = items.stream().
reduce((t1, t2) -> t1.getI() > t2.getI() ? t1 : t2)
.orElse(null);
There is not
orgetT()
in this case, it's simply used as a label in this example. And it can't be used to order the Stream; it's the order of the items in the original list that is important.
– Druckles
1 hour ago
add a comment |
You can still use the reduction to get this thing done. If t1 is larger, then only it will keep t1. In all the other cases it will keep t2. If either t2 is larger or t1 and t2 are the same, then it will eventually return t2 adhering to your requirement.
Thing t = items.stream().
reduce((t1, t2) -> t1.getI() > t2.getI() ? t1 : t2)
.orElse(null);
You can still use the reduction to get this thing done. If t1 is larger, then only it will keep t1. In all the other cases it will keep t2. If either t2 is larger or t1 and t2 are the same, then it will eventually return t2 adhering to your requirement.
Thing t = items.stream().
reduce((t1, t2) -> t1.getI() > t2.getI() ? t1 : t2)
.orElse(null);
edited 36 mins ago
answered 1 hour ago


Ravindra RanwalaRavindra Ranwala
9,24031635
9,24031635
There is not
orgetT()
in this case, it's simply used as a label in this example. And it can't be used to order the Stream; it's the order of the items in the original list that is important.
– Druckles
1 hour ago
add a comment |
There is not
orgetT()
in this case, it's simply used as a label in this example. And it can't be used to order the Stream; it's the order of the items in the original list that is important.
– Druckles
1 hour ago
There is no
t
or getT()
in this case, it's simply used as a label in this example. And it can't be used to order the Stream; it's the order of the items in the original list that is important.– Druckles
1 hour ago
There is no
t
or getT()
in this case, it's simply used as a label in this example. And it can't be used to order the Stream; it's the order of the items in the original list that is important.– Druckles
1 hour ago
add a comment |
Stream is not necessary bad if you do things in two steps :
1) Find the i
value that has more occurrences in the Iterable
(as you did)
2) Search the last element for this i
value by starting from the end of items:
Thing t =
items.stream()
.max(Comparator.comparingLong(Thing::getI))
.mapping(firstMaxThing ->
ListIterator li = items.listIterator(items.size());
while(li.hasPrevious()) {
Thing current = li.previous()
if (li.previous().getI() == firstMaxThing.getI()){
return current;
}
}
throw new RuntimeException("should not occur here if max was found");
).orElse(null)
We could write it with StreamSupport
to make it more elegant :
Thing t =
items.stream()
.max(Comparator.comparingLong(Thing::getI))
.mapping(firstMaxThing ->
Iterable<Thing> iterable = () -> items.listIterator(items.size());
return
StreamSupport.stream(iterable.spliterator(), false)
.filter(i -> i.getI() == firstMaxThing.getI())
.findFirst().get(); // here get() cannot fail as *max()* returned something.
)
.orElse(null)
add a comment |
Stream is not necessary bad if you do things in two steps :
1) Find the i
value that has more occurrences in the Iterable
(as you did)
2) Search the last element for this i
value by starting from the end of items:
Thing t =
items.stream()
.max(Comparator.comparingLong(Thing::getI))
.mapping(firstMaxThing ->
ListIterator li = items.listIterator(items.size());
while(li.hasPrevious()) {
Thing current = li.previous()
if (li.previous().getI() == firstMaxThing.getI()){
return current;
}
}
throw new RuntimeException("should not occur here if max was found");
).orElse(null)
We could write it with StreamSupport
to make it more elegant :
Thing t =
items.stream()
.max(Comparator.comparingLong(Thing::getI))
.mapping(firstMaxThing ->
Iterable<Thing> iterable = () -> items.listIterator(items.size());
return
StreamSupport.stream(iterable.spliterator(), false)
.filter(i -> i.getI() == firstMaxThing.getI())
.findFirst().get(); // here get() cannot fail as *max()* returned something.
)
.orElse(null)
add a comment |
Stream is not necessary bad if you do things in two steps :
1) Find the i
value that has more occurrences in the Iterable
(as you did)
2) Search the last element for this i
value by starting from the end of items:
Thing t =
items.stream()
.max(Comparator.comparingLong(Thing::getI))
.mapping(firstMaxThing ->
ListIterator li = items.listIterator(items.size());
while(li.hasPrevious()) {
Thing current = li.previous()
if (li.previous().getI() == firstMaxThing.getI()){
return current;
}
}
throw new RuntimeException("should not occur here if max was found");
).orElse(null)
We could write it with StreamSupport
to make it more elegant :
Thing t =
items.stream()
.max(Comparator.comparingLong(Thing::getI))
.mapping(firstMaxThing ->
Iterable<Thing> iterable = () -> items.listIterator(items.size());
return
StreamSupport.stream(iterable.spliterator(), false)
.filter(i -> i.getI() == firstMaxThing.getI())
.findFirst().get(); // here get() cannot fail as *max()* returned something.
)
.orElse(null)
Stream is not necessary bad if you do things in two steps :
1) Find the i
value that has more occurrences in the Iterable
(as you did)
2) Search the last element for this i
value by starting from the end of items:
Thing t =
items.stream()
.max(Comparator.comparingLong(Thing::getI))
.mapping(firstMaxThing ->
ListIterator li = items.listIterator(items.size());
while(li.hasPrevious()) {
Thing current = li.previous()
if (li.previous().getI() == firstMaxThing.getI()){
return current;
}
}
throw new RuntimeException("should not occur here if max was found");
).orElse(null)
We could write it with StreamSupport
to make it more elegant :
Thing t =
items.stream()
.max(Comparator.comparingLong(Thing::getI))
.mapping(firstMaxThing ->
Iterable<Thing> iterable = () -> items.listIterator(items.size());
return
StreamSupport.stream(iterable.spliterator(), false)
.filter(i -> i.getI() == firstMaxThing.getI())
.findFirst().get(); // here get() cannot fail as *max()* returned something.
)
.orElse(null)
answered 7 mins ago


davidxxxdavidxxx
65.8k66494
65.8k66494
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.
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%2f54535632%2fusing-java-8-stream-methods-to-get-the-last-max-value%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
4,0wqNYqw,foO6PO2pF7uXxQIOS8NmZmpzo0qa zETZF,DYDeilmGm