So I've created a stream which comes from a List but I'm having some trouble converting it into a <ObjectType>, here's what I've tried:
ObjectType sco = getList().stream()
.filter(p -> p.getValue() == value)
.findFirst(); //also tried .orElse(null);
would anyone, please, be so kind as to suggest where I'm going wrong?
(I apologize if this has been asked before but I couldn't find a discussion on this particular topic (or didn't know the proper terms to search for))
Thanks in advance!
findFirst() gives you an Optional and you then have to decide what to do if it's not present. So findFirst().orElse(null) should give you the object or null if it's not present
You could just do a .get() on the Optional, but that could be regarded as poor practice since get() will throw an exception if Optional has no content. You should normally assert presence/absence of the Optional and decide what to do in each case (that's why it's there - so that you know something is truly optional and you have to determine what to do)
If you have an action you want to perform on object presence, and you don't want to do anything on absence, you can call .ifPresent() and provide a lambda as an argument. That will be called with the contained object, if present.
As of Java 9, a further solution would be to use Optional.ifPresentOrElse()
I think you may be looking for findFirst().or Else(null). findFirst() will return an Optional - empty in the case of an empty steam.
Unless I misunderstood your comment. Have you tried this, or did you try orElse(null) without findFirst()?
Related
I know I can filter a stream to get only those elements that are not null, and then do with them whatever I need. Something like this:
myList.stream().filter(element -> element != null).doOtherThings...
Is there a way to assert that the elements are not null in a stream function, so that it goes through all elements and if it finds one being null, it throws an exception? I've been thinking of something like the following:
myList.stream().assert(Objects::nonNull).doOtherThings...
Use something like
.map(Objects::requireNonNull)
You just need to apply an operation which will throw an exception, but otherwise passes the argument through.
Although, unless there is a good reason not to iterate the list multiple times, it might be clearer to separate the checking and the processing:
if (myList.stream().anyMatch(Objects::isNull)) {
throw ...
}
// Do things with list.
There are some very good suggestions already. Allow me to supplement. If what you are after is an assertion as in an assert statement, I would like to make this explicit in the code in order to guide the reader about my purpose. To assert that your original list doesn’t contain any nulls:
assert ! myList.contains(null);
If the assertion is to be checked somewhere down the stream pipeline, the simple way is:
assert myList.stream().map(this::transform).allMatch(Objects::nonNull);
If you don’t want to create a separate stream for the assertion but prefer to assert in the middle of your existing stream pipeline, use for example:
myList.stream()
.peek(e -> { assert e != null; })
.toArray();
You may worry that the use of peek is not so nice, which is also why I mention this option last. peek is documented to exist “mainly to support debugging” (quote taken out of its context), so you may say that it’s related to the purpose of assert and thus defend its use in this case.
To the map method I prefer to use peek method. I think it is more expressive then uing map method that has to return some value.
list.stream()
.peek(Objects::requireNonNull)
However what i think is hard to understand is that stream is not executed until the collect() is called. That is why doing this kind of conditional logic is hard using streams. To be honest if you want to achieve the desired effect you have to do something like this.
list.stream()
.peek(Objects::requireNonNull)
.collect(Collectors.toList())
.stream()
.map(t -> do whatever ... )
I'm trying my hand at using Optional as much as I can over normal null checks; and I ran into a suggestion by my IDE (IntelliJ):
Can be replaced by a singular expression in functional style.
Here is the code in question, the line in question:
Entry entry = maybeBytes.isPresent() ? Entry.deserialize(maybeBytes.get()) : new Entry();
I've looked a bit here, but couldn't find a usage or at least see one that would fit my case here. I'm pretty new to the lambda features.
How about:
Entry entry = maybeBytes.map(Entry::deserialize).orElseGet(Entry::new);
If maybeBytes contains a value, it will be passed to the function you provide to map(), and you'll get an Optional<Entry> with the result (and if maybeBytes was empty, you'll get an empty Optional<Entry>). orElseGet() will give you the contents of the Optional<Entry> if it's nonempty, and otherwise, it will give you the result of evaluating the function you pass to it (in this case, the constructor of Entry).
Pressing Alt+Enter when you see such suggestions will apply them, and you'll see the result yourself :)
In my case it was orElse() which fit to my needs. I do not needed to do extra deserialization.
instead of isPresent() combined with get() certainly does the trick…
return maybeBytes.isPresent() ? maybeBytes.get() : new Entry();
you can use
return maybeBytes.orElse(new Entry());
I want to use Optional for a method which returns a List
Lets say the function is
public Output getListOfSomething() {
// In some cases there is nothing to return and hence it makes sense to have return
// type as Optional here
}
Hence the function looks like :
public Optional<List<String>> getListOfSomething() {
// return something only when there is some valid list
}
Now I want to do something if the list is present so something like :
Optional<List<String>> listOfSomething = getListOfSomething();
int size = 0;
listOfSomething.ifPresent(size = listOfSomething.get().size());
I am new to Optional and have gone through the articles about Optional and it seems like this should work however am getting syntax error in my IDE :
method ifPresent is not applicable for the arguments (void).
I wanted to get some help from developers who might be more fluent with lamdas in java 8.
It's important to think about the Semantics here.
Your method could return a List, or "no list".
If it returns a List, it could return an Empty list.
You should ask, "is there a semantic reason to distinguish between an Empty List, and No List?" Sometimes there is a good design reason to make the difference, but it is rare. Think long and hard before deciding that Empty and Null are different in your case. Part of the reason to avoid No List, is that it reduces "special cases" that the client code has to consider. For example, if they have to do something for every item returned, but you could also return null, they have to do a special check for null before going into a for each loop. A for each does nothing if the list is empty.
If a "No List" is distinct from an "Empty List" in your problem domain, then it is sometimes useful to return wrapper class that helps client code distinguish between those conditions, and handle them appropriately. Optional is one such generic class, but your domain may call for something more specific (even if it mimics the functionality of Optional, it might have better semantic definition).
The true functional-programming way is the following:
size = listOfSomething.map(List::size).orElse(0);
But it would be much better to return an empty List instead of Optional.
ifPresent requires a Consumer interface to work. You could do the following:
Optional<List<String>> listOfSomething = getListOfSomething();
Integer[] size = {0};
listOfSomething.ifPresent(list -> size[0]=list.size())
But as stated by Tagir Valeev it would be better to do:
size = listOfSomething.map(List::size).orElse(0);
And it would also be better to return an empty List or even a Stream maybe.
JDK 8 adds classes called Optional, OptionalDouble, OptionalInt, and OptionalLong that offer a way to handle situations in which a value may or may not be present. In the past, I would normally use the value null to indicate that no value is present. However, this can lead to null pointer exceptions if an attempt is made to dereference a null reference. As a result, frequent checks for a null value were necessary to avoid generating an exception. These classes provide a better way to handle such situations.
The first and most general of these classes is Optional.
It is important to understand that an Optional instance can either contain a value of type T(bounded type) or be empty. In other words, an Optional object does not necessarily contain a value.
Optional(value-based class) does not define any constructors, but it does define
several methods that let you work with Optional objects. For example, I can
determine if a value is present, obtain the value if it is present, obtain a
default value when no value is present, and construct an Optional value.
I tried something like this,
Optional<String> noVal = Optional.empty();
Optional<String> hasVal = Optional.of("ABCDEFGH");;
if(noVal.isPresent())
System.out.println("This won't be displayed");
else
System.out.println("noVal has no value");
if(hasVal.isPresent())
System.out.println(hasVal.get());
String defStr = noVal.orElse("Default String");
System.out.println(defStr);
But, i am unable to make out how to use it with collections so as to handle null? Can someone.
Your question lacks information about what you are actually going to do. Without a description of an operation, e.g. showing the code performing the action without using Optional, we can’t tell you how to do the same using Optional or whether this is possible at all.
One way of dealing with references which might be null is to construct an Optional via Optional.ofNullable(…). This can also be used within an action that is applied to Collection elements:
List<String> list=Arrays.asList("hello", null, "world", null);
list.forEach(x->Optional.ofNullable(x).ifPresent(System.out::println));
However, most operations on collections which you want to formulate using new Java 8 features are good candidates for the stream API. While forEach is suitable for a simple action, even the short detour via Optional makes it complex enough to benefit from the Stream API:
list.stream().filter(Objects::nonNull).forEach(System.out::println);
does the same without nested operations.
So Optional is a good return type for a single element which might be absent, e.g. like for Stream.findAny, but when processing collections, there are usually better alternatives.
I know the subject may be a bit in advance as the JDK8 is not yet released (and not for now anyway..) but I was reading some articles about the Lambda expressions and particularly the part related to the new collection API known as Stream.
Here is the example as given in the Java Magazine article (it is an otter population algorithm..):
Set<Otter> otters = getOtters();
System.out.println(otters.stream()
.filter(o -> !o.isWild())
.map(o -> o.getKeeper())
.filter(k -> k.isFemale())
.into(new ArrayList<>())
.size());
My question is what happen if in the middle of the Set internal iteration, one of the otter is null?
I would expect a NullPointerException to be thrown but maybe am I still stuck in the previous development paradigm (non-functional), can someone enlighten me as how this should be handled?
If this really throw a NullPointerException, I find the feature quite dangerous and will have to be used only as below:
Developer to ensure there is no null value (maybe using a previous
.filter(o -> o != null))
Developer to ensure the application is never
generating null otter or a special NullOtter object to deal with.
What is the best option, or any other option?
Although the answers are 100% correct, a small suggestion to improve null case handling of the list itself with Optional:
List<String> listOfStuffFiltered = Optional.ofNullable(listOfStuff)
.orElseGet(Collections::emptyList)
.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
The part Optional.ofNullable(listOfStuff).orElseGet(Collections::emptyList) will allow you to handle nicely the case when listOfStuff is null and return an emptyList instead of failing with NullPointerException.
Stuart's answer provides a great explanation, but I'd like to provide another example.
I ran into this issue when attempting to perform a reduce on a Stream containing null values (actually it was LongStream.average(), which is a type of reduction). Since average() returns OptionalDouble, I assumed the Stream could contain nulls but instead a NullPointerException was thrown. This is due to Stuart's explanation of null v. empty.
So, as the OP suggests, I added a filter like so:
list.stream()
.filter(o -> o != null)
.reduce(..);
Or as tangens pointed out below, use the predicate provided by the Java API:
list.stream()
.filter(Objects::nonNull)
.reduce(..);
From the mailing list discussion Stuart linked:
Brian Goetz on nulls in Streams
Current thinking seems to be to "tolerate" nulls, that is, to allow them in general, although some operations are less tolerant and may end up throwing NPE. See the discussion of nulls on the Lambda Libraries expert group mailing list, specifically this message. Consensus around option #3 subsequently emerged (with a notable objection from Doug Lea). So yes, the OP's concern about pipelines blowing up with NPE is valid.
It's not for nothing that Tony Hoare referred to nulls as the "Billion Dollar Mistake." Dealing with nulls is a real pain. Even with classic collections (without considering lambdas or streams) nulls are problematic. As fge mentioned in a comment, some collections allow nulls and others do not. With collections that allow nulls, this introduces ambiguities into the API. For example, with Map.get(), a null return indicates either that the key is present and its value is null, or that the key is absent. One has to do extra work to disambiguate these cases.
The usual use for null is to denote the absence of a value. The approach for dealing with this proposed for Java SE 8 is to introduce a new java.util.Optional type, which encapsulates the presence/absence of a value, along with behaviors of supplying a default value, or throwing an exception, or calling a function, etc. if the value is absent. Optional is used only by new APIs, though, everything else in the system still has to put up with the possibility of nulls.
My advice is to avoid actual null references to the greatest extent possible. It's hard to see from the example given how there could be a "null" Otter. But if one were necessary, the OP's suggestions of filtering out null values, or mapping them to a sentinel object (the Null Object Pattern) are fine approaches.
If you just want to filter null values out of a stream, you can simply use a method reference to java.util.Objects.nonNull(Object). From its documentation:
This method exists to be used as a Predicate, filter(Objects::nonNull)
For example:
List<String> list = Arrays.asList( null, "Foo", null, "Bar", null, null);
list.stream()
.filter( Objects::nonNull ) // <-- Filter out null values
.forEach( System.out::println );
This will print:
Foo
Bar
An example how to avoid null e.g. use filter before groupingBy
Filter out the null instances before groupingBy.
Here is an example
MyObjectlist.stream()
.filter(p -> p.getSomeInstance() != null)
.collect(Collectors.groupingBy(MyObject::getSomeInstance));
If you do not want to iterate two times (filter + map or any). Try this.
private static void trimAll() {
String[] emtLne = {"", " ", " cc ", null, " xx "};
System.out.println(Arrays.stream(emtLne).map(val -> (val != null) ? val.trim() : "").collect(Collectors.joining()));
}
Output
ccxx