I have an optionalIdList ( Optional<Set<String>> optionalIdList) that I want to iterate over, and then convert back to Optional<Set<String>>. My code thus far is like this:
optionalIdList
.map(
idList ->
idList.stream()
.map(
id ->
filterIds(
partnerIds
)))
.flatMap(streamOfLists -> streamOfLists.map(item -> item.orElseGet(ImmutableSet::of)));
The filterIds list returns Optional<Set<String>>
However with my current solution I get the following error:
Required type: Optional<Set<String>>
Provided: Optional<Object>
Is there a nice way to do what I want to do?
EDIT: For some reason I assumed filterIds returns a single String, and not an Optional<Set<String>> as you wrote it does.
Here's the updated answer:
Optional<Set<String>> output =
optionalIdList.map(idList -> idList.stream()
.map(id -> filterIds(partnerIds))
.filter (Optional::isPresent)
.map (Optional::get)
.flatMap (Set::stream)
.collect(Collectors.toSet()));
Related
This question already has answers here:
Java 8 collecting the list that is already present in object
(2 answers)
Rewrite double nested for loop as a Java 8 stream
(2 answers)
Closed 2 years ago.
So I have lists stored inside of another list.
And inside of that lists there a different objects.
I want to get a specific object based on an attribute.
Human robert = building.getRoomList()
.stream()
.filter(room -> room.getEmployeeList()
.stream()
.filter(human -> human.getName().equals("Robert")))
.findFirst().get();
Why doesn't it work?
Try this:
Human robert = building.getRoomList().stream()
.map(Room::getRoomList)
.flatMap(Collection::stream)
.filter(human -> human.getName().equals("Robert"))
.findFirst()
.orElseThrow(() -> new RuntimeException("Robert not found!"));
Why doesn't it work?
Stream::filter requires a Predicate<T> and returns the very same Stream<T>. As long as you nest filter in filter, this would never work because the outer one requires Predicate<T> while the inner one returns Stream<T> which is clearly not compatible.
You might want to use flatMap:
Human robert = building.getRoomList()
.stream() // Stream<Room>
.flatMap(room -> room // Stream<Human> flatmapped from:
.getEmployeeList() // .. for each Room get List<Human>
.stream() // .. for each Room have Stream<Human>
.filter(human -> human.getName() // .. for each Room keep the one named
.equals("Robert"))) // .. Robert
.findFirst() // find the first Robert, the Human
.orElse(null); // or result in null
Remember the predicate human -> human.getName().equals("Robert")) is not null-safe neither when human is null nor when its name is null. For the null-safety, flat-map like this:
.flatMap(room -> room.getEmployeeList()
.stream()
.filter(Objects::nonNull)
.filter(human -> "Robert".equals(human.getName())))
You can do it using Stream.flatMap:
Optional<Human> robert = building.getRoomList().stream()
.flatMap(room -> room.getEmployeeList().stream())
.filter(human -> human.getName().equals("Robert"))
.findFirst();
robert.ifPresent(r -> /* do something with Robert */);
Stream.flatMap maps each room to a stream of humans and the returned stream consists of all the humans of all the rooms, flattened (i.e. not as sublists or substreams).
You are doing .findFirst() on RoomList only but you need to do .findFirst() on inner list means EmployeeList of every Room also and transform Room into Human using .map(), like
building.getRoomList()
.stream()
.map(room -> room.getEmployeeList()
.stream()
.filter(human -> human.getName().equals("Robert"))
.findFirst().get())
.findFirst().get();
Which can be simplified using flatMap to flatten then EmployeeList then get findFirst
building.getRoomList()
.flatMap(e -> room.getEmployeeList().stream())
.filter(human -> human.getName().equals("Robert"))
.findFirst().get();
Note: It's better to use .orElse() rather calling .get()
Here are some lines of code that need to convert into Java.
val geojsonSeq = for (kml <- kmlSeq) yield kmlConverter.toGeoJson(kml)
I tried to convert using for each loop in java using lamda operator but not able to get it.
kmlSeq.foreach((Function1<Option<Kml>, U>) (f) -> {
});
Every time I am getting compile-time error like:
"The method foreach(Function1<Option,U>) is ambiguous for the type Seq<Option>"
Apart from this if I'm going to use normally for each loop in java like :
for(Option<Kml> kml : kmlSeq)
{
}
In that case kmlSeq is throwing error like :
"Can only iterate over an array or an instance of java.lang.Iterable"
But in scala the kmlSeq looping into Option object.
You can use either of two ways (Assuming return type of toGeoJson is String)
List<String> result = kmlSeq
.stream()
.flatMap(kmlOpt ->
kmlOpt.map(Stream::of).orElseGet(Stream::empty)
)
.map(kml -> kmlConverter.toGeoJson(kml))
.collect(Collectors.toList());
or
List<String> result = kmlSeq
.stream()
.flatMap(kmlOpt ->
kmlOpt.map(kml ->
Stream.of(kmlConverter.toGeoJson(kml))
).orElseGet(Stream::empty)
)
.collect(Collectors.toList());
To print, do this
result.forEach(System.out::println);
I have list of Map.
List(Map(term_id -> 20898477-2374-4d4c-9af0-8ed9c9829c94),
Map(term_id -> 6d949993-1593-4491-beae-eb9bf8abcf27),
Map(term_id -> 1123c413-3ffd-45ed-8215-dd1bccb3a48f))
and want to get all value and check if a term_id already exist in above list of Map.
This can be done with iterating list and checking value of each map. But I want something more efficient and one liner. I am okay with either of Java or Scala approach.
This question may be naive, but I am not getting at how to proceed. I am new to Java/Scala.
Expected Output:
List(20898477-2374-4d4c-9af0-8ed9c9829c94, 6d949993-1593-4491-beae-eb9bf8abcf27,
123c413-3ffd-45ed-8215-dd1bccb3a48f)
I think flatMap is what you want:
val maplist=List(Map("term_id" -> "20898477-2374-4d4c-9af0-8ed9c9829c94"), Map("term_id" -> "6d949993-1593-4491-beae-eb9bf8abcf27"), Map("term_id" -> "1123c413-3ffd-45ed-8215-dd1bccb3a48f"))
maplist.flatMap(_.values)
//res0: List[String] = List(20898477-2374-4d4c-9af0-8ed9c9829c94, 6d949993-1593-4491-beae-eb9bf8abcf27, 1123c413-3ffd-45ed-8215-dd1bccb3a48f)
maplist.flatMap(_.keys)
//res1: List[String] = List(term_id, term_id, term_id)
you can use below code to get list of values
val maplist=List(Map("term_id" -> "20898477-2374-4d4c-9af0-8ed9c9829c94"), Map("term_id" -> "6d949993-1593-4491-beae-eb9bf8abcf27"), Map("term_id" -> "1123c413-3ffd-45ed-8215-dd1bccb3a48f"))
maplist.map(x=>x.get("term_id")
Output:
List[Option[String]] = List(Some(20898477-2374-4d4c-9af0-8ed9c9829c94), Some(6d949993-1593-4491-beae-eb9bf8abcf27), Some(1123c413-3ffd-45ed-8215-dd1bccb3a48f))
Edit:
Basically I want to filter all the entries based on whether entry.getObject() is a string that contains value "value".
So I have a block of code that looks something like this:
list.stream()
.filter((entry) -> entry.getObject() != null)
.filter((entry) -> entry.getObject() instanceof String)
.filter((entry) -> ((String)entry.getObject()).toLowerCase().contains(value))
.collect(Collectors.toList());
The main problem is that I can't figure out how to structure this to persist the value of entry.getObject(), and I can't figure out how to manipulate the output of of entry.getObject() without losing sight of the entry that yielded the value. Earlier attempts looked more like this:
list.stream()
.map((entry) -> entry.getObject())
.filter((object) -> entry instanceof String)
.map((object) -> (String)entry)
.filter((str) -> str.toLowerCase().contains(value))
/* ... */
But then I couldn't figure out any way to relate it to the entry in the list that I started out with.
A possible solution might look like this:
list.stream()
.filter((entry) -> Arrays.stream(new Entry[] {entry})
// Map from entry to entry.getObject()
.map((entry) -> entry.getObject())
// Remove any objects that aren't strings
.filter((object) -> entry instanceof String)
// Map the object to a string
.map((object) -> (String)entry)
// Remove any strings that don't contain the value
.filter((str) -> str.toLowerCase().contains(value))
// If there is a product remaining, then entry is what I want
.count() > 0)
.collect(Collectors.toList());
This way, we can split off and analyze entry.getObject() without multiple calls to get the value back at each step.
You could do something like
list.stream()
.map( (e) -> new Entry(e, e.getObject()) )
.filter( (p) -> p.getValue() instanceof String )
//...
.map( (p) -> p.getKey() )
.collect(Collectors.toList());
Using Map.Entry or swing.Pair (or roll your own tuple like structure)
In short, I have this code, and I'd like to get an specific element of the array using a condition and lambda. The code would be something like this:
Preset[] presets = presetDALC.getList();
Preset preset = Arrays.stream(presets).select(x -> x.getName().equals("MyString"));
But obviously this does not work. In C# would be something similar but in Java, how do I do this?
You can do it like this,
Optional<Preset> optional = Arrays.stream(presets)
.filter(x -> "MyString".equals(x.getName()))
.findFirst();
if(optional.isPresent()) {//Check whether optional has element you are looking for
Preset p = optional.get();//get it from optional
}
You can read more about Optional here.
Like this:
Optional<Preset> preset = Arrays
.stream(presets)
.filter(x -> x.getName().equals("MyString"))
.findFirst();
This will return an Optional which might or might not contain a value. If you want to get rid of the Optional altogether:
Preset preset = Arrays
.stream(presets)
.filter(x -> x.getName().equals("MyString"))
.findFirst()
.orElse(null);
The filter() operation is an intermediate operation which returns a lazy stream, so there's no need to worry about the entire array being filtered even after a match is encountered.
Do you want first matching, or all matching?
String[] presets = {"A", "B", "C", "D", "CA"};
// Find all matching
List<String> resultList = Arrays.stream(presets)
.filter(x -> x.startsWith("C"))
.collect(Collectors.toList());
System.out.println(resultList);
// Find first matching
String firstResult = Arrays.stream(presets)
.filter(x -> x.startsWith("C"))
.findFirst()
.orElse(null);
System.out.println(firstResult);
Output
[C, CA]
C
One-liner since Java 8:
Preset found = Stream.of(presets)
.filter(p -> p.getName().equals("MyString"))
.findFirst().orElseThrow();
Avoid declaring Optional<>, that returned from findFirst as a variable or a parameter. It is designed for return types / "one-liner" styles.
see javadoc API Note
see 26 Reasons Why Using Optional Correctly