I'm having simple DataStructure
public class DataStructure {
private String key;
private String value;
//get, set
}
And I need to return value from `List' based on key and I want to do it Java8 way, with streams. I think code speaks for himself:
public class Main {
public static void main(String args[]) {
List<DataStructure> dataList = new ArrayList<>();
dataList.add(new DataStructure("first", "123"));
dataList.add(new DataStructure("second", "456"));
System.out.println(findValueOldSchool(dataList, "third")); //works ok
System.out.println(findValueStream(dataList, "third")); //throws NoSuchElementException
}
static String findValueOldSchool(List<DataStructure> list, String key) {
for (DataStructure ds : list) {
if (key.equals(ds.getKey())) {
return ds.getValue();
}
}
return null;
}
static String findValueStream(List<DataStructure> list, String key) {
return list.stream()
.filter(ds -> key.equals(ds.getKey()))
.findFirst()
.get().getValue();
}
}
How can I modify findValueStream()
to not throw NoSuchValueException while I search for non existing key? I don't want to return Optional<String>
because this method is already used in a lot of places in project. And, ofcourse I'v tried map
, ifPresent
, anyMatch
, just can't find the right way to do it.
You shall use Stream.findFirst
with an Optional.orElse
like :
static String findValueStream(List<DataStructure> list, String key) {
return list.stream() // initial Stream<DataStructure>
.filter(ds -> key.equals(ds.getKey())) // filtered Stream<DataStructure>
.map(DataStructure::getValue) // mapped Stream<String>
.findFirst() // first Optional<String>
.orElse(null); // or else return 'null'
}
Note: The above uses the Stream.map
to map the stream of DataStructure
to a corresponding stream of value
.
use orElse
to return a default value if the Optional has an empty state:
This also means you'll need to map to DataStructure::getValue
first like so:
return list.stream()
.filter(ds -> key.equals(ds.getKey()))
.findFirst()
.map(DataStructure::getValue)
.orElse(null);
just replacing get
with orElse
will not suffice:
return list.stream()
.filter(ds -> key.equals(ds.getKey()))
.findFirst()
.orElse(null)
.getValue();
As this time you'll get a NullPointerException
instead of a NoSuchElementException
in the case of an empty optional.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With