I am trying to get a collection of Objects, from a Collection using streams in Java8 based on some predicate
Here is what I have tried, but there is some syntax error in this.:
Collection<object> objectCollectionNew = objectCollection.stream().filter(o -> objectCollection.stream().filter( x- > x.isTrue == o.isTrue));
So basically I want to get a collection of objects out of the objectCollection based on my Predicate. Also I am unsure about how to collect this into my Collection<object>.
.collect(Collectors.to ?? )
Some help will be appreciated.
It's not entirely clear what you are trying to do, but if you want to find all elements of your collection whose isTrue is equal to isTrue of some other element of the collection, you would do it like this:
objectColelction.stream()
.filter(o -> objectColelction.stream().anyMatch(x -> x.isTrue == o.isTrue))
.collect(Collectors.toList());
It seems like you want to use a flatMap :
Collection<object> objectCollectionNew = objectCollection.stream()
.flatMap(o -> objectCollection.stream().filter(x -> x.isTrue == o.isTrue))
.collect(Collectors.toList());
I had a similar problem which looks like an error in the Eclipse syntax parser. I solved it by adding parenthesis
Collection<object> objectCollectionNew = objectCollection.stream()
.filter( x -> {return x.isTrue == o.isTrue;} )
.collect(Collectors.toList());
Just answering on the syntax aspect, not how to best solve your filtering itself.
Related
I am using Java 8
method1() -> returns a Map<String,Map<String,Set<String>>>.
If I chain the method calls this way -> method1().get("A").get("B") a NullPointerException could happen.
So I am using the following strategy to avoid using the traditional if( != null) code:
Optional.ofNullable(method1()).map(x -> x.get("A")).map(y -> y.get("B")) but the this code return an Optional and I need that returns the Set<String>.
How can I cast it, and in case of null (in the case of the get methods returns null) how returns null?
Thanks in advance.
Polishing the code by gamgoon a little bit:
Set<String> result = Optional.of(method1())
.map(x -> x.get("A"))
.map(y -> y.get("B"))
.orElse(Collections.emptySet());
System.out.println(result);
Output in case either key is not in a map where looked up:
[]
You may recognize the result of printing an empty collection. In places where you want a collection, you should not accept a null. Use an empty collection to signify that there are no elements. In the same vein I have assumed that your method1() may return an empty map but not null. So we don’t need ofNullable() when converting into an Optional — the simple of() is fine.
use orElse like
Set<String> result = Optional.ofNullable(method1())
.map(x -> x.get("A"))
.map(y -> y.get("B"))
.orElse(null);
This is the original piece of code:
Set<StatuteType> statuteTypes = registration.getStudent().getStudentStatutesSet()
.stream()
.map(StudentStatute_Base::getType)
.collect(Collectors.toSet());
I want to wrap everything in an Optional to avoid null pointers and all. If the student does not exist or the statutesSet does not exist.
What I have:
Set<StatuteType> statuteTypes = Optional.of(registration)
.map(Registration_Base::getStudent)
.map(student -> student.getStudentStatutesSet())
.flatMap(Collection::stream)
.map(StudentStatute_Base::getType)
.collect(Collectors.toSet())
.orElse(null);
Would something like this be in someway possible? I want to avoid null checks in this chain, and if there's any null just return a simple null as well instead getting an exception.
Normally what I think would be logical would be to use a flatMap as described here but it doesn't seem to be correct in this case, because the Optional flatmap returns an Optional.
Here's a simple way of doing it:
Set<StatuteType> statuteTypes = Optional.ofNullable(registration)
.map(Registration_Base::getStudent)
.map(student -> student.getStudentStatutesSet())
.map(Collection::stream)
.orElseGet(Stream::empty) // Exit Optional, enter stream
.map(StudentStatute_Base::getType)
.collect(Collectors.toSet());
However, it does not result in a null set. Collections should never be null, only empty. I would recommend this approach. The whole point of using an Optional object is so you never have to deal with null values.
Collection::stream does not return an Optional, so you should not use flatMap here. You should keep using map on the optional.
.map(Collection::stream) gives you an Optional<Stream<Statute>>. You seem to be trying to call the stream's map and collect methods on this. But you need to first call Optional.map before you can do that.
You should also use Optional.ofNullable if registration could be null:
Set<StatuteType> statuteTypes = Optional.ofNullable(registration)
.map(Registration_Base::getStudent)
.map(student -> student.getStudentStatutesSet())
.map(Collection::stream)
.map(x -> // Optional.map
x.map(StudentStatute_Base::getType) // Stream.map
.filter(Objects::nonNull) // I assume you want to filter out the statute types which are null?
.collect(Collectors.toSet())
)
.orElse(null);
I have a collection which has a field of type Set with some values. I need to create a new set collecting all these values.
I am wondering if this is possible using lambda expressions.
Below is the code line :
Set<String> teacherId = batches.stream()
.filter(b -> !CollectionUtils.isEmpty(b.getTeacherIds()))
.map(b -> b.getTeacherIds())
.collect(Collectors.toSet());
The problem is post map operation, it contains a collection of set of strings. So collect operation returns a Set<Set<String>> but i am looking to aggregate all the values to a single set.
You need to use flatMap instead of map:
Set<String> teacherIds =
batches.stream()
.flatMap(b -> b.getTeacherIds().stream())
.collect(Collectors.toSet());
Note that the filtering is redundant for empty collections - streaming an empty collection will just result in an empty stream, which won't affect the final result.
If getTeacherIds() could return null, however, you'd still have to handle it. Using filter(Objects::nonNull) would suffice, and save you the dependency on Apache Commons.
You can use flatMap to obtain a flat Stream of all the values, and then collect to a Set<String>:
Set<String> teacherId =
batches.stream()
.filter(b -> !CollectionUtils.isEmpty(b.getTeacherIds()))
.flatMap(b -> b.getTeacherIds().stream())
.collect(Collectors.toSet());
If you care that that getTeacherIds() is not null, use it explicitly via !=, that CollectionUtils.isEmpty just hides stuff. Especially since if getTeacherIds() returns an Empty collection - that is handled just fine by flatMap, so to me that is not needed at all.
Set<String> teacherIds = batches
.stream()
.filter(x -> x.getTeacherIds() != null)
.flatMap(x -> x.getTeacherIds().stream())
.collect(Collectors.toSet());
I am wondering if this is possible using lambda expressions.
I capture the last fish, :).
Set<String> teacherIds = batches.stream()//v--- the class of `x`
.map(XClass::getTeacherIds)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.collect(Collectors.toSet());
Note: I'm sorry I'm forget to tell you if the getTeacherIds copy the internal IDs to a new set of IDs, the code above is appropriate for you. since it is read the IDs from XClass once.
I want to remove objects from the list on a certain filter and there are more than one objects.
list.stream().filter(g->g.getName().equalsIgnoreCase("String")).forEach(result ->{
/* is it possible to get the index of the result here?
.remove(), will iterate through the list again. I don't want that.
*/
list.remove(result);
});
There is no way to get an index at this point, but modifying the list you’re streaming over, is not supported anyway. You would likely get a ConcurrentModificationException when you try.
Use the dedicated API for this operation:
list.removeIf(g -> g.getName().equalsIgnoreCase("String"));
The alternative would be collecting the elements you want to keep into a new List:
List<String> result = list.stream()
.filter(g -> !g.getName().equalsIgnoreCase("String"))
.collect(Collectors.toList());
you can using Collection#removeIf instead, for example:
list.removeIf(g -> g.getName().equalsIgnoreCase("String"));
Sorry if can't help for you
list.stream().filter(g->g.getName().equalsIgnoreCase("String")).forEach(result ->{
list.indexOf(result);
});
I'm used to C# and the lambda expressions, but i couldn't filter a java list based on certain criterias.
Ex:
List<MyObject> list;
I need to get all the MyObject that have a isMyFlag() true.
In C# is really easy using IEnumerable... Is there any similar to IEnumerable in Java?
See the new Stream API in Java 8
You need to do a filter and then collect the results in a list using the Stream API:
list.stream().filter(x -> x.isMyFlag()).collect(Collectors.toList());
With lambdas you could do the following:
List<MyObject> filteredList = list.stream().filter(myObj -> myObj.isMyFlag())
.collect(Collectors.toList());
To use the Stream API you need to call the stream() method. This is perhaps a surprise coming from C# as you don't need to do this, but once you have got over that hurdle it should be much the same.
List<MyObject> list2 = list.stream()
.filter(m -> m.isMyFlag())
.collect(Collectors.toList());