You solved 80%: first collect and filter. This will give a new collection using Java 8 streams.
Literally: last
Then pick the last from the filtered collection, e.g. on list
using list.get(lastIndex)
where int lastIndex = list.size()-1
.
The last is a bit ambiguous, so I have 2 approaches ️
List<Person> personList = getAllPersons();
// typo: name of List should be plural e.g. `personActiveList` or `activePersons`
List<Person> personActive = personList.stream()
.filter(person -> person.getPersonStatus()!=null)
.toList();
// the last in order of appearance
Person lastInActiveList = personActice.get(personActice.size()-1); // may throw NPE if list empty
// the last who was active by some Instant timestamp
List<Person> sortByLastActive = personList.stream()
.filter(person -> person.getPersonStatus()!=null)
.sorted(Person::getTimestamp()) # sort by Instant property
.toList();
Person lastRecentlyActice = sortByLastActive.get(sortByLastActive.size()-1); // may throw NPE if list empty
Note: For brevity I used toList()
as terminator (since Java 16).
You could also use collect(Collectors.toList())
from older Java versions. Beware: Differences of Java 16's Stream.toList() and Stream.collect(Collectors.toList())?
⚠️ Caution: all random get
operations on list can throw a NullPointerException
(NPE) if the list is empty. This should be tested using if (list.isEmpty())
before to prevent illegal access.
Trick: reverse to first
The trick here as commented by Boris is to reverse the list before opening the stream, thus before it becomes filtered/collected as result. Afterwards you can directly pick the first.
List<Person> personActiveReversed = Collections.reverse(personList).stream() // reverse to get last elements first
.filter(person -> person.getPersonStatus()!=null)
.toList();
// may throw NPE if list empty
Person last = personActiveReversed.get(0);
// safer: directly on stream
Optional<Person> last = Collections.reverse(personList).stream() // reverse before streaming
.filter(person -> person.getPersonStatus()!=null)
.findFirst(); // originally the last or empty
// evaluate optional
if (last.isPresent()) {
System.out.println("found the last: " + last.get());
} else {
System.out.println("nobody found at last :(");
}
Explained:
see comments by Boris below and on question: use Collections.reverse
before .stream
to reverse an ordered list (from last to first). Then reversedList.get(0)
will get the originally last element.
findFirst()
is the new terminator, returning Java 8 type-wrapper Optional
. This is null-safe but requires a further test or convenience-methods like orElse(defaultObject)
, e.g. last.orElse(null)
.
See also