How to convert an Optional<T> into a Stream<T>? - java

I want to prepend a stream with an Optional. Since Stream.concat can only concatinate Streams I have this question:
How do I convert an Optional<T> into a Stream<T>?
Example:
Optional<String> optional = Optional.of("Hello");
Stream<String> texts = optional.stream(); // not working

If restricted with Java-8, you can do this:
Stream<String> texts = optional.map(Stream::of).orElseGet(Stream::empty);

In Java-9 the missing stream() method is added, so this code works:
Stream<String> texts = optional.stream();
See JDK-8050820. Download Java-9 here.

You can do:
Stream<String> texts = optional.isPresent() ? Stream.of(optional.get()) : Stream.empty();

I can recommend Guava's Streams.stream(optional) method if you are not on Java 9. A simple example:
Streams.stream(Optional.of("Hello"))
Also possible to static import Streams.stream, so you can just write
stream(Optional.of("Hello"))

If you're on an older version of Java (lookin' at you, Android) and are using the aNNiMON Lightweight Stream API, you can do something along the lines of the following:
final List<String> flintstones = new ArrayList<String>(){{
add("Fred");
add("Wilma");
add("Pebbles");
}};
final List<String> another = Optional.ofNullable(flintstones)
.map(Stream::of)
.orElseGet(Stream::empty)
.toList();
This example just makes a copy of the list.

It can depend of how you want to convert empty optional to stream element.
If you want to interpret it as "nothing" (or "no element"):
Stream<String> texts = optional.stream(); // since JDK 9
Stream<String> texts = optional.map(Stream::of).orElseGet(Stream::empty); // JDK 8
But if you want to interpret it as null:
Stream<String> texts = Stream.of(optional.oreElse(null));

A nice library from one of my ex collegues is Streamify. A lot of collectors, creating streams from practicly everything.
https://github.com/sourcy/streamify
Creating a stream form an optional in streamify:
Streamify.stream(optional)

Related

apache commons: FailableFunction and Function inside same FailableStream

Is there any way to use both FailableFunction and Function lambdas into a single .map chaining stream?
Function<String, Organization> hook = (id) -> this.organizationRepository.findById(id).get();
FailableFunction<Organization, Organization, MpiException> failableSave = (r) -> this.organizationRepository.save(r);
List<String> ids;
Failable.stream(ids)
.map(hook)
.map(failableSave)
.collect(Collectors.toList());
I'm getting:
The method map(FailableFunction<String,R,?>) in the type Streams.FailableStream is not applicable for the arguments (Function<String,Organization>)
Problem here is that sometimes I need to use Function and other times I need to use FailableFunction.
Any ideas about how to use them into same stream mapping chaining?
Maybe not the most elegant solution, but since nobody else came up with something:
You could use a method reference to implicitly convert a Function into a FailableFunction:
Failable.stream(ids)
.map(hook::apply)
.map(failableSave)
.collect(Collectors.toList());

How to filter strings from one stream which are not contained in another sream?

I have two streams of Strings like :
Stream<String> thisWeekFile = Files.lines(thisWeekPath);
Stream<String> lastWeekFile = Files.lines(lastWeekPath);
In comparison to last week this weeks file can have the same strings, some strings added or some strings removed. For now I'm only interested in the strings which were present in last weeks file but not any more in this weeks file. How do i get those strings? I tried
lastWeekFile.filter(e->!thisWeekFile.anyMatch(e));
The above giving an error :String can not be converted to predicate.
Idealy i want something like
lastWeekFile.filter(e->!thisWeekFile.contains(e));
You need to collect the streams and then possibly remove(updated existin) entries for lastWeekFile :
Set<String> thisWeekFile = Files.lines(thisWeekPath).collect(Collectors.toSet());
List<String> lastWeekFile = Files.lines(lastWeekPath)).collect(Collectors.toList());
lastWeekFile.removeIf(e -> !thisWeekFile.contains(e));
Using Files.readLines() method that returns List instead of stream it can be done without stream api:
List<String> thisWeekFile = Files.readAllLines(thisWeekPath);
List<String> lastWeekFile = Files.readAllLines(lastWeekPath);
lastWeekFile.removeAll(thisWeekFile);
It should be
lastWeekFile.filter(e->Files.lines(thisWeekPath).noneMatch(o -> o.equals(e)))...;
Note that you cannot consume the same stream more than once, so you'll have to generate this week's Stream multiple times.

Java 8 lambda expression is present

First I need to check if data is present in list then get else set default or empty value on a Java 8 stream.
Currently I am using below code without isPresent but I dont know how to use isPresent in java8.
I am trying something below which is not perfect:
String isScheme = (this.mapProgramApproaches.stream().findFirst().isPresent())? this.mapProgramApproaches.stream().findFirst().get().getIsScheme().toString() : "0";
Where as mapProgramApproaches this is set.
Don't use isPresent() (it makes no sense to run the Stream pipeline twice).
You can use map to map the value of the Optional to the required String, and then
use orElse() to return a default value when the Optional value is not present:
String isScheme = this.mapProgramApproaches.stream()
.findFirst()
.map(o->o.getIsScheme().toString())
.orElse("0");
Maybe you are looking for something like this:
String isScheme = this.mapProgramApproaches.stream()
.findFirst()
.map(p -> p.getIsScheme().toString())
.orElse("0");
I'm not sure about context in which you are doing this, but I suppose that you would like to check whether some object is scheme and then do something with that. In that case I would suggest implement it like this:
List<String> mapProgramApproaches = new ArrayList<>();
mapProgramApproaches.stream()
.filter(this::isScheme)
.findFirst()
.ifPresent(this::doYourCode)
.orElse(defaultValue);
It will make your code cleaner. And will help to avoid additional conditionals!

Can Java 8 Streams use multiple items from mapping pipeline

I have some data stored in a JPA Repository that I am trying to process. I would like to be able to use Java 8 Streams to do so, but can not figure out how to get the required information. This particular 'Entity' is actually only for recovery, so it holds items that would need to be processed after something like a power-fail/restart.
Using pre-Java 8 for-loops the code would look like:
List<MyEntity> deletes = myEntityJpaRepository.findByDeletes();
for (MyEntity item : deletes) {
String itemJson = item.getData();
// use a Jackson 'objectMapper' already setup to de-serialize
MyEventClass deleteEvent = objectMapper.readValue(itemJson, MyEventClass.class);
processDelete(deleteEvent, item.getId());
}
The problem arises from the two parameter method called at the very end. Using Streams, I believe I would do:
// deletes.stream()
// .map(i -> i.getData())
// .map(event -> objectMapper.readValue(event, MyEventClass.class))
// .forEach(??? can't get 'id' here to invoke 2 parameter method);
I have a solution (without Streams) that I can live with. However I would think this problem comes up a lot, thus my question is: IN GENERAL, is there a way using Streams to accomplish what I am trying to do?
Why not a Pair return on your map operation:
.map(i -> new Pair<>(i.getData(), i.getId()))
.map(pair -> new Pair<>(objectMapper.readValue(pair.getLeft(), MyEventClass.class), pair.getRight())
.forEach(p -> processDelete(pair.getLeft(), pair.getRight()))
I did not compile this, so there might be minor things to fix. But in general, you would need a Holder to pass your objects to the next stage in such a case. Either a Pair or some type or even a array.
Why not doing it simply this way?
deletes.forEach(item ->
processDelete(objectMapper.readValue(item.getData(), MyEventClass.class),
item.getId()));
This is a start at least, I guess it is dependent on why you want to use stream and how much you want to make it more functional
List<MyEntity> deletes = myEntityJpaRepository.findByDeletes();
deletes.stream().foreach(item -> {
String itemJson = item.getData();
// use a Jackson 'objectMapper' already setup to de-serialize
MyEventClass deleteEvent = objectMapper.readValue(itemJson, MyEventClass.class);
processDelete(deleteEvent, item.getId());
});

Java 8 - filter empty string from List not working

I would like to remove an empty String from the List of Strings.
Here is what I tried, using the stream API:
list.stream().filter(item-> item.isEmpty()).collect(Collectors.toList());
After that empty string is still present in the list. What am I missing?
filter() keeps the elements that match the predicate. Soyou need the inverse predicate:
list.stream().filter(item-> !item.isEmpty()).collect(Collectors.toList());
This will also not modify the original list. It will create a filtered copy of the original list. So you need
list = list.stream().filter(item-> !item.isEmpty()).collect(Collectors.toList());
If you want to modify the original list, you should use
list.removeIf(item -> item.isEmpty());
or simply
list.removeIf(String::isEmpty);
Since java 11 there is a new method Predicate::not.
So you can write it like that:
list.stream().filter(Predicate.not(String::isEmpty)).collect(Collectors.toList())
I suspect you are not keeping the result. The result is returned, the original list is not altered as this is functional programming style.
list = list.stream().filter(item-> !item.trim().isEmpty()).collect(Collectors.toList());
Maybe the string contains whitespaces? Replace item -> item.isEmpty() with item -> !item.trim().isEmpty()
you are collecting the empty elements :)
you want the not empty so invert the predicate
List<String> xxx = list.stream().filter(item -> !item.isEmpty()).collect(Collectors.toList());
additionally, the stream is not modifying the original list, so Collect(Collectrors.toList()) is returning the result of the predicate :)
You are removing non-empty strings (check your filter condition). Try:
list.stream().filter(item -> !item.isEmpty()).collect(Collectors.toList());
Otherwise, you may need to check that you're removing blanks as well:
list.stream().filter(item -> !item.trim().isEmpty()).collect(Collectors.toList());
You are not removing empty Strings from the list, you were retrieving them. Your filter condition is wrong.
Try like this:
List<String> collect = list.stream().filter(item -> !item.trim().isEmpty()).collect(Collectors.toList());
you can follow below example, it may help you
String[] firstArray = {"test1", "", "test2", "test4", "", null};
firstArray = Arrays.stream(firstArray).filter(s -> (s != null && s.length() > 0)).toArray(String[]::new);
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5-SNAPSHOT</version>
</dependency>
import org.apache.commons.lang3.StringUtils;
//Java8 new api
strings.removeIf(StringUtils::isBlank);
//stream strings=strings.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
Might be your List contains null. So first filter with null check
then again filter on empty
list.stream().filter(item -> null != item).filter(item -> !item.isEmpty()).collect(Collectors.toList());
If you have apache commons lang lib use Apache StringUtils isNotBlank
list.stream().filter(item -> StrinUtils.isNotBlank(item)).collect(Collectors.toList());

Categories

Resources