Reputation: 698
I have a requirement to validate a field against some predefined values (that can grow in future). So for this I have created a Enum and defined a method that returns the stream of the allowed values.
public enum EnumDemo {
VERSION("1.0.0","2.0.3");
private List<String> ver;
EnumDemo(String... ver) {
this.ver = Arrays.asList(ver);
}
public List<String> getVer() {
return ver;
}
public static Stream<EnumDemo> stream() {
return Arrays.stream(EnumDemo.values());
}
}
Now I need to validate a field against the values defined in this Enum.
I'm using:
Optional<EnumDemo> ab = EnumDemo.stream()
.map(l -> {l.getVer().stream()
.filter(c -> c.equals("2.0.3"))
.findFirst();})
.findFirst();
System.out.println(ab.get().getVer());
But it is giving me compilation error. Any help would be appreciated.
Edit:
Compilation Error:
The method map(Function<? super EnumDemo,? extends R>) in the type Stream<EnumDemo> is not applicable for the arguments ((<no type> l) -> {})
Upvotes: 1
Views: 586
Reputation: 8363
You should write it this way:
Optional<EnumDemo> ab = EnumDemo.stream().filter(l -> l.getVer().contains("2.0.3"))
.findFirst();
By the way, it wasn't working because you used {}
for the lambda expression, so it was expecting a return
statement in the {}
. You could either remove the {}
(along with the ;
) or add in the return
.
Anyway the original codes looked confusing, not sure if I guessed the intention correctly, but this implementation should be clearer.
Based on your comment, this is what you need:
EnumDemo.stream().flatMap(l -> l.getVer().stream())
.filter("2.0.3"::equals)
.findAny()
.ifPresent(System.out::println);
Holger commented that there is a shorter and more meaningful way, with better performance:
if(EnumDemo.stream()
.anyMatch(l -> l.getVer().contains(userString))) {
System.out.println(userString);
}
Upvotes: 4
Reputation: 7368
You are using lambda
expression and not returning any value so it is giving compilation error. It is better to use ifPresent()
String val="2.0.3";
EnumDemo.stream()
.flatMap(l -> l.getVer().stream())
.filter(c -> c.equals(val))
.findAny()
.ifPresent(x -> System.out.println(x));
Upvotes: 2
Reputation: 19926
To understand it, you have to think about lambdas. Lambdas represent interface
s but are specially treated by the JVM, so not every Lambda needs a class to represent. (Stateless lambdas can be just methods).
Now when looking at the map()
method in the Stream
interface:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
You see that it expects an implementation of the Function
interface. You now have many different ways to provide that mapper. In this example lets map from Object
to String
:
.map(o -> o.toString())
.map(o -> {
return o.toString();
})
.map(Object::toString)
.map(new Function<Object, String>(){
@Override
public String apply(Object o){
return o.toString();
}
})
Your current code uses the 2. approach. But without a return
statement. This is even better seen when looking at the anonymous class at 4.. It seems natural, that when not using a return
statement in a method that no value is returned.
And that's why you get the compilation error.
You just have to add the return
statement:
.map(l -> {
return l.getVer().stream()
.filter(c -> c.equals("2.0.3"))
.findFirst();
});
Or remove the brackets {}
:
.map(l -> l.getVer().stream()
.filter(c -> c.equals("2.0.3"))
.findFirst());
Or even use the approach provided by @Jai in his answer. Which works even better, than what you currently have.
Upvotes: 3