I am very new to Java 8 features like streams, filters and stuff and the tell the truth, I haven't been writing in Java for more than a year.
Here is my problem if someone could give a suggestion .
#Override
public ArrayList<Agent> getAllEnabledAgents() throws Exception {
ArrayList<Agent> agents = repository.all(); //redis repository
Stream<Agent> result = agents.stream().filter(a-> a.equals(a.getConfigState().Enabled)); //enum
return result; //I dont know how to return result or whether I am using stream correctly.
}
The main idea is that I want return all enabled agents. gerConfigState() returns an enum (__ConfigState). not sure If am doing this correctly.
Use the collect-metod of the Stream. Also, your filter looks a bit strange, since the variable a is an object of class Agent.
So perhaps something like this:
agents.stream()
.filter(a -> a.getConfigState() == Enabled)
.collect(Collectors.toList());
Then again, like the comment states, you might just be better off filtering this with a query.
Your filter condition is not correct (I assume getConfigState() returns an enum). You can use something like below:
Stream<Agent> streamAgent = agents.stream().filter(a-> a.getConfigState() == Enabled);
return streamAgent.collect(Collectors.toList());
Thanks for the help. This is the final version:
#Override
public List<Agent> getAllEnabledAgents() throws Exception {
return repository.all()
.stream()
.filter(a-> a.getConfigState() == ConfigState.Enabled)
.collect(Collectors.toList());
}
Related
I have some problems with using Optional.ifPresent statement. I would like to reduce number of NullPointerExceptions, so I decided to use Optional values.
Also I am trying to avoid a ladder of if statements anti-pattern.
So I implemented Optional.isPresent statement. But it's not really that what I expected.
Please look at these listings:
This is a part of my service:
if (getAllComputerProducers().isPresent()) {
if (isComputerProducerAlreadyExist(computerProducer))
return new ResponseEntity<>(HttpStatus.CONFLICT);
}
computerProducerRepository.save(computerProducer);
return new ResponseEntity<>(HttpStatus.CREATED);
getAllComputerProducers function looks like that:
private Optional<List<ComputerProducer>> getAllComputerProducers() {
return Optional.ofNullable(computerProducerRepository.findAll());
}
As you can see, this function returns Optional of List.
The isComputerProducerAlreadyExist function is implemented like that:
private boolean isComputerProducerAlreadyExist(ComputerProducer computerProducer) {
return getAllComputerProducers()
.get()
.stream()
.anyMatch(producer -> producer.getProducerName()
.equalsIgnoreCase(computerProducer.getProducerName()));
}
It's so much code and I believe that it could be made simpler.
My target is to reduce code to one line command like:
getAllCimputerProducers().ifPresent(***and-here-some-anyMatch-boolean-function***)
but I can't insert there a function which returns something. How can I do it?
Regards to everyone :)
You could try something like
private boolean isComputerProducerAlreadyExist(ComputerProducer computerProducer){
return this.getAllComputerProducers()
.map((List<ComputerProducer> computerProducers) -> computerProducers.stream()
.anyMatch(producer -> producer.getProducerName().equalsIgnoreCase(computerProducer.getProducerName())))
.orElse(Boolean.FALSE);
}
Or instead of loading all computer producers load only the ones using its name.
private boolean isComputerProducerAlreadyExist(ComputerProducer computerProducer){
return computerProducerRepository.findByName(computerProducer.getProducerName()).isEmpty();
}
And as far as I know Spring supports also "exist" methods for repositories without even the need to load the Entity.
The following should work
Predicate<ComputerProducer> cpPredicate = producer -> producer.getProducerName()
.equalsIgnoreCase(computerProducer.getProducerName());
boolean compProdExists = getAllCimputerProducers()
.map(list -> list.stream()
.filter(cpPredicate)
.findFirst()))
.isPresent();
You can pass the computerProducer.getProducerName() to repository to get the existing record. Method name will be 'findByProducerName(String producerName)', if producerName has unique constraint, return type will be Optional<ComputerProducer>, else Optional<List<ComputerProducer>>. However, JPA returns empty list instead of null, so optional on list is not required.
I want to simplify my code without using too many If-Else condition.
The business logic I want is:
I retrieved data of customer's account from DB
I want to check whether each customer is qualified for applying new product
If She/He has the account, then passed
Otherwise failed.
Repository
public interface MyRepository extends JpaRepository<Account, String>{
Optional<List<Account>> findAcctByCustoNo(String custNo);
}
The logic code
Optional<List<Account>> accounts = myRepo.findAcctByCustoNo(auth.getCustNo());
if(!accounts.isPresent()) {
return "invalid param";
}
accounts.ifPresent(list->list.stream()
.filter(type -> type.getAccCd().equals("typeA") || type.getAccCd().equals("typeB"))
.forEach(System.out::println));
The code hasn't finished yet. I need to check, after filtering the data, if it still return null value, I want to return "No Data" message, something like this. Or apply another method or else.
And I don't know how to do it properly. Because What I can think is add create new instance after filtering, and check it with isPresent again. But I have a feeling that I can do it inside the accounts instance.
Please enlighten me.
I just use this Optional feature recently. I spent a lot of time understanding the method inside it. I was thinking to utilize map, but again, I have no idea how to implement it in the right way.
What about this ?
Do all the filtering you want, then use findAny (cheaper than count() since it will stop as soon as it has a match) and check the result
Optional<List<Account>> accounts = myRepo.findAcctByCustoNo(auth.getCustNo());
return accounts //
.map(List::stream) //
.orElseGet(Stream::empty) //
.filter(type -> type.getAccCd().equals("typeA") || type.getAccCd().equals("typeB")) //
.findAny() //
.orElse(null)
!= null;
Explanation
map your optional List to a stream
if not, use an empty stream
then, filter all you want
findAny ? we are good.
orElse, return null
And finally, check for null.
Test code on simpler data :
#Test
public void test_checkArray() {
Assert.assertFalse(this.checkArray(null));
Assert.assertFalse(this.checkArray(Arrays.asList()));
Assert.assertFalse(this.checkArray(Arrays.asList("not a!", "b", "c")));
Assert.assertTrue(this.checkArray(Arrays.asList("a", "b", "c")));
}
private boolean checkArray(final List<String> a) {
return Optional //
.ofNullable(a) //
.map(List::stream) //
.orElseGet(Stream::empty) //
.filter(aa -> "a".equals(aa)) //
.findAny() //
.orElse(null)
!= null;
}
Not sure how you intend to use the info after, but if you just need to see if the customer qualifies, you can try
boolean qualify = accounts.stream()
.filter(type -> type.getAccCd().equals("typeA") || type.getAccCd().equals("typeB"))
.findFirst()
.isPresent();
This will return true if the customer qualifies, otherwise false.
You can rearrange code like this
Optional.of(myRepo.findAcctByCustoNo(auth.getCustNo()))
.filter(.....)
.orElse(......);
Optional methods return Optional object, thus it allows method chaining.
I have a POJO:
class MyObject {
private Double a;
private String b;
//constructor, getter + setter
}
Some function is creating a list of this POJO. Some values for a might be null, so I want to replace them with 0.0. At the moment I am doing it like this.
public List<MyObject> fetchMyObjects(Predicate predicate) {
List<MyObject> list = getMyListsOfTheDatabase(predicate);
list
.forEach(myObject -> {
if (myObject.getA() == null) {
myObject.setA(0.0);
}
});
return list;
}
Is there a way to integrate the forEach in the return? Something like
return list
.stream()
.someStatement();
It's not about, if this is the best place to convert the nulls to zero, but rather a questions to better understand the streaming api.
Use the peek function
Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
public List<MyObject> fetchMyObjects(Predicate predicate) {
return getMyListsOfTheDatabase(predicate)
.stream()
.peek(it -> if(it.getA() == null) it.setA(0.0))
.collect(Collectors.toList());
}
While others have been happy to answer your question as it stands, allow me to step a step back and give you the answer you didn’t ask for (but maybe the answer that you want): You don’t want to do that. A stream operation should be free from side effects. What you are asking for is exactly a stream operation that has the side effect of modifying the original objects going into the stream. Such is poor code style and likely to confuse those reading your code after you.
The code you already have solves your problem much more nicely than any combined stream pipeline.
What you may want to have if you can modify your POJO is either a constructor that sets a to 0 if null was retrieved from the database, or method that does it that you may call from list.forEach:
list.forEach(MyObject::setAToZeroIfNull);
It's not about, if this is the best place to convert the nulls to
zero, but rather a questions to better understand the streaming api.
That’s fair. In any case I will let this answer stand for anyone else popping by.
You can't return the same List instance with a single statement, but you can return a new List instance containing the same (possibly modified) elements:
return list.stream()
.map(myObject -> {
if (myObject.getA() == null) {
myObject.setA(0.0);
}
return myObject;
})
.collect(Collectors.toList());
Actually you should be using List::replaceAll:
list.replaceAll(x -> {
if(x.getA() == null) x.setA(0.0D);
return x;
})
forEach doesn't have a return value, so what you might be looking for is map
return list
.stream()
.map(e -> {
if (e.getA() == null) e.setA(0d);
return e;
})
.whateverElse()...
The following would be fine:
list.stream()
.filter(obj -> obj.getA() == null)
.forEach(obj -> obj.setA(0.0));
return list;
However in your case just returning a Stream might be more appropriate (depends):
public Stream<MyObject> fetchMyObjects(Predicate predicate) {
return getMyListsOfTheDatabase(predicate);
}
public Stream<MyObject> streamMyObjects(List<MyObject> list) {
return list.stream()
.peek(obj -> {
if (obj.getA() == null) {
obj.setA(0.0);
}
});
}
I personally never used peek, but here it corrects values.
On code conventions, which are more string in the java community:
Indentation: Java took 4 as opposed to C++'s 3 as more separate methods,
and less indentation was expected. Debatable but okay.
For generic type parameters often a single capital like T, C, S.
For lambda parameters short names, often a single letter, hence I used obj.
I have an Try<Option<Foo>>. I want to flatMap Foo into a Bar, using it using an operation that can fail. It's not a failure if my Option<Foo> is an Option.none(), (and the Try was a success) and in this case there's nothing to do.
So I have code like this, which does work:
Try<Option<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo).map(Option::of) /* ew */)
.getOrElse(Try.success(Option.none()); // double ew
}
Try<Bar> mappingFunc(Foo foo) throws IOException {
// do some mapping schtuff
// Note that I can never return null, and a failure here is a legitimate problem.
// FWIW it's Jackson's readValue(String, Class<?>)
}
I then call it like:
fooOptionTry.flatMap(this::myFlatMappingFunc);
This does work, but it looks really ugly.
Is there a better way to flip the Try and Option around?
Note 1: I actively do not want to call Option.get() and catch that within the Try as it's not semantically correct. I suppose I could recover the NoSuchElementException but that seems even worse, code-wise.
Note 2 (to explain the title): Naively, the obvious thing to do is:
Option<Try<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo));
}
except this has the wrong signature and doesn't let me map with the previous operation that could have failed and also returned a successful lack of value.
When you are working with monads, each monad type combine only with monads of same type. This is usually a problem because the code will come very unreadable.
In the Scala world, there are some solutions, like the OptionT or EitherT transformers, but do this kind of abstractions in Java could be difficult.
The simple solution is to use only one monad type.
For this case, I can think in two alternatives:
transform fooOpt to Try<Foo> using .toTry()
transform both to Either using .toEither()
Functional programmers are usually more comfortable with Either because exceptions will have weird behaviors, instead Either usually not, and both works when you just want to know why and where something failed.
Your example using Either will look like this:
Either<String, Bar> myFlatMappingFunc(Option<Foo> fooOpt) {
Either<String, Foo> fooE = fooOpt.toEither("Foo not found.");
return fooE.flatMap(foo -> mappingFunc(foo));
}
// Look mom!, not "throws IOException" or any unexpected thing!
Either<String, Bar> mappingFunc(Foo foo) {
return Try.of(() -> /*do something dangerous with Foo and return Bar*/)
.toEither().mapLeft(Throwable::getLocalizedMessage);
}
I believe this is simply a sequence function (https://static.javadoc.io/io.vavr/vavr/0.9.2/io/vavr/control/Try.html#sequence-java.lang.Iterable-) that you are looking for:
Try.sequence(optionalTry)
You can combine Try.sequence and headOption functions and create a new transform function with a little better look, in my opinion, also you can use generic types to get a more reusable function :) :
private static <T> Try<Option<T>> transform(Option<Try<T>> optT) {
return Try.sequence(optT.toArray()).map(Traversable::headOption);
}
If I understand correctly, you want to :
keep the first failure if happens
swap the second when mapping to json for an empty option.
Isn t it simpler if you decompose your function in such a way:
public void keepOriginalFailureAndSwapSecondOneToEmpty() {
Try<Option<Foo>> tryOptFoo = null;
Try<Option<Bar>> tryOptBar = tryOptFoo
.flatMap(optFoo ->
tryOptionBar(optFoo)
);
}
private Try<Option<Bar>> tryOptionBar(Option<Foo> optFoo) {
return Try.of(() -> optFoo
.map(foo -> toBar(foo)))
.orElse(success(none())
);
}
Bar toBar(Foo foo) throws RuntimeException {
return null;
}
static class Bar {
}
static class Foo {
}
The solution of throughnothing and durron597 helped me there. This is my groovy test case:
def "checkSomeTry"() {
given:
def ex = new RuntimeException("failure")
Option<Try<String>> test1 = Option.none()
Option<Try<String>> test2 = Option.some(Try.success("success"))
Option<Try<String>> test3 = Option.some(Try.failure(ex))
when:
def actual1 = Try.sequence(test1).map({ t -> t.toOption() })
def actual2 = Try.sequence(test2).map({ t -> t.toOption() })
def actual3 = Try.sequence(test3).map({ t -> t.toOption() })
then:
actual1 == Try.success(Option.none())
actual2 == Try.success(Option.some("success"))
actual3 == Try.failure(ex)
}
I couldn't find a way to do the following with Java's Optional:
if (SOME_OBJECT != null) {
doSomething(SOME_OBJECT);
} else {
doSomethingElse();
}
By using Optional, I don't mean mean replacing SOME_OBJECT == null with Optional.ofNullable(SOME_OBJECT).isPresent(), which a much longer syntax than simply checking if null.
What I would expect is something like:
Optional.ofNullable(SOME_OBJECT)
.ifPresent(this::doSomething)
.orElse(this::doSomethingElse);
I couldn't find an API like the one I just wrote. Does it exist? If so, what is it? If not, why not? :)
The second piece of code looks like an anti-pattern :( Why? Perhaps Java's architects prevented this syntax on purpose...
As mentioned in this Blog Article, Optionals will get a new method in Java 9: void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction). So, with Java, 8 you don't have something like that at the moment.
As BdoubleB97 (Bdubzz) stated, Java 9 will implement Optional#ifPresentOrElse which will take a Consumer<T> which will be applied if the Optional<T> is present, and a Runnable which will be executed if the Optional<T> is empty.
You can either update now to the Java 9 Early Access build, or you can build the method yourself with the following:
public <T> void ifPresentOrElse(Optional<T> optional, Consumer<? super T> action, Runnable emptyAction) {
if (optional.isPresent()) {
action.accept(optional.get());
} else {
emptyAction.run();
}
}
As said Java 8 does not have a construct to do exactly what you want.
I know, it's ugly, far less readable than a simple if/then/else but you can do this:
Optional.ofNullable(someObject)
.map(obj -> {
System.out.println("present");
return obj;
})
.orElseGet(() -> {
System.out.println("not present");
return null;
});
The only side effect is that you have always return something.
Or on the other hand you can handle cleanly the case isPresent().
Optional.ofNullable(someObject).ifPresent(obj -> {
System.out.println("present");
});