I am very new to lambdas in Java.
I have started using it as i found them quite interesting
but i still don't know how to use them completely
I have a list of uuids and for each uuid i want to call a function which takes two parameters : first is a string and second is uuid
I am passing a constant string for each uuid
I have written a following code but its not working
uuids.stream()
.map(uuid -> {"string",uuid})
.forEach(AService::Amethod);
It is method which is another class AService
public void Amethod(String a, UUID b) {
System.out.println(a+b.toString());
}
A lambda expression has a single return value, so {"string",uuid} doesn't work.
You could return an array using .map(uuid -> new Object[]{"string",uuid}) but that won't be accepted by your AService::Amethod method reference.
In your example you can skip the map step:
uuids.stream()
.forEach(uuid -> aservice.Amethod("string",uuid));
where aservice is the instance of AService class on which you wish to execute the Amethod method.
uuids.stream().forEach(uuid -> AService.Amethod("string", uuid));
You can write something closer to your current code given a Pair class, but 1) you end up with more complicated code; 2) Java standard library doesn't have one built-in. Because of 2), there are quite a few utility libraries which define one. E.g. with https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html, it would be
uuids.stream()
.map(uuid -> Pair.of("string",uuid))
.forEach(pair -> AService.Amethod(pair.getLeft(), pair.getRight()));
Related
My code:
final List<Employee> empList= getEmployeeList();
String empid = "1234";
Employee selectedEmp = new Employee();
for (Employee e1: empList) {
if (empid .equals(e1.getEmpid()))
selectedEmp = e1;
}
}
Now I want to rewrite the above code in Java 8.
I've tried the following, but without success. I can't figure out translate the if-statement:
empList.stream()
.foreach( <how to apply if condition here>)
forEach() isn't the appropriate tool here.
Firstly there's a method Iterable.forEach() which you can invoke directly on a list without creating a stream, secondly Stream.forEach() is not encouraged to be used in such a way by the Stream API documentation, it should be used with care in cases when you have no other tools suitable for the task.
Instead, you can use combination filter() + findFirst(), which produces result of type Optional.
To provide a default value for the case when employee wasn't found (like in your code a dummy Employee object created via no-args constructor) you can use Optional.orElseGet() which expects a Supplier that would be applied only when needed (when optional is empty).
public Employee findEmployee(String empid) {
return getEmployeeList().stream()
.filter(e -> empid.equals(e.getEmpid()))
.findFirst()
.orElseGet(Employee::new);
}
I strongly recommend you to get familiar with these tutorials on streams and lambda expressions
I am injecting a kotlin class into my java code. The kotlin class has two methods with nearly identical signatures:
fun <R> isFluxAuthorizedFor(
strings: List<StringRequest>,
then: (responses: List<StringResult>) -> Flux<R>
): Flux<R>
and
fun <R> isFluxAuthorizedFor(
string: StringRequest,
then: (per: StringResult) -> Flux<R>
): Flux<R> {
The kotlin class supports this overloading just fine.
However, I'm having a devil of a time getting my IDE to use the correct method. I have a method which matches the signature of the former:
private Flux<AuthorizedStrings> collectResults(List<StringResult> responses)
{
//not yet implemented
return null;
}
And yet, when I try and call the injected class' method, I get compilation errors:
List<StringRequest> allStrings = new ArrayList<StringRequest>();
Flux<UserReadAuthorizations> test = authCheck.isFluxAuthorizedFor(allStrings, (it) -> this.collectResults(it) );
The IDE makes two suggestions:
"change type of 'it' to 'List<StringResult>'"
"change method 'collectResults(List<StringResult>)' to 'collectResults(StringResult)'"
both of which imply that Java (or at least the compiler) can't figure out that I'm trying to call the other method. Is this a problem trying to integrate Java 8 and Kotlin? A quirk of the IDE? (I'm using Spring Tool Suite) Some silly user error that I've not yet been able to rubber-duck through?
I played with your code and found that IntelliJ tripped over the type of the lambda as a whole. I had to cast it -> this.collectResults(it) to the type Kotlin was expecting:
List<StringRequest> allStrings = new ArrayList<>();
Flux<UserReadAuthorizations> test = authCheck.isFluxAuthorizedFor(
allStrings,
(Function1<List<StringResult>, Flux<AuthorizedStrings>>) (it -> this.collectResults(it))
);
The signature of your methods themselves was not an issue. Hope this helps you in STS as well.
I have a library written in kotlin which i want to use in my Java program, but i don't know how to call an asynchronous method correctly.
/*This is my asynchronous kotlin method from the library*/
fun getNames(callback: (List<String>) -> Unit) = ...
/*In Java i want to call this method*/
List<String> names = getNames(...);
What parameter do i have to pass into the function in Java?
IntelliJ says i need something like this: 'kotlin.jvm.functions.Function1<? super java.util.List<String>,kotlin.Unit>' But i don't know how to instantiate such a class.
Ok, first of all give it a look at this great response from Kirill Rakhman.
Now, the result given by a callback from a asynchronous operation will come from the parameter. In this case it'll be the (List<String>) at the fun getNames().
A simple usage of this function in JAVA (8+) can look like this :
getNames(
strings -> {
strings.forEach(System.out::println);
return Unit.INSTANCE;
}
);
I have the following classes:
abstract class Executor {
String executorType;
public Executor(String executorType) {this.executorType = executorType;}
public void execute(String dataContent);
}
class Data {
String dataType;
String dataContent;
}
Given a list of Datas, and a list of Executors(concrete ones that extend Executor), I want that each executor will call execute only on the data with the same type as their types. In other words executor will execute on data only if executor.executorType == data.dataType
How can I do it shortly and with good performance, using streams, collectors and other things that are supplied by Java 8?
Here's an example that I've made, but I think I can do better:
(Notes:
1. In my example, I create a map between executors and data on which they can run their execute() method. However, if there's a solution that skips the map creation and instantly run execute(), that would be better
2. In my example I assumed that Executor is a concrete class, not abstract, just for the convenience.
List<Executor> executorList = Arrays.asList(new Executor("one"), new Executor("two"), new Executor("three"));
List<Data> dataList = Arrays.asList(new Data("one","somecontent"), new Data("two","someOtherContent"), new Data("one","longContent"));
Map<List<Executor>, List<Data>> stringToCount = dataList.stream().collect(
Collectors.groupingBy(t-> executorList.stream().filter(n -> n.executorType.equals(t.getName())).collect(Collectors.toList())));
How can I do it shortly and with good performance, using streams, collectors and other things that are supplied by Java 8?
So what is exactly your goal? Good performance or using Java 8 Streams?
With streams it would be something like:
dataList
.forEach(data -> executorList
.stream()
.filter(executor -> Objects.equals(data.dataType, executor.executorType))
.findAny()
.map(executor -> executor.execute(data.dataContent)));
Not sure about the syntax, but something along the lines.
But I'd actually make a Map<String, Executor> on Executor.executorType first and then just executors.get(data.dataType). You could also implement a VoidExecutor which does nothing and call
executors.getOrDefault(data.dataType, VoidExecutor.INSTANCE).execute(data.dataContent);
With a hash map you may expect contant-time lookups.
I am trying to understand the ifPresent() method of the Optional API in Java 8.
I have simple logic:
Optional<User> user=...
user.ifPresent(doSomethingWithUser(user.get()));
But this results in a compilation error:
ifPresent(java.util.functionError:(186, 74) java: 'void' type not allowed here)
Of course I can do something like this:
if(user.isPresent())
{
doSomethingWithUser(user.get());
}
But this is exactly like a cluttered null check.
If I change the code into this:
user.ifPresent(new Consumer<User>() {
#Override public void accept(User user) {
doSomethingWithUser(user.get());
}
});
The code is getting dirtier, which makes me think of going back to the old null check.
Any ideas?
Optional<User>.ifPresent() takes a Consumer<? super User> as argument. You're passing it an expression whose type is void. So that doesn't compile.
A Consumer is intended to be implemented as a lambda expression:
Optional<User> user = ...
user.ifPresent(theUser -> doSomethingWithUser(theUser));
Or even simpler, using a method reference:
Optional<User> user = ...
user.ifPresent(this::doSomethingWithUser);
This is basically the same thing as
Optional<User> user = ...
user.ifPresent(new Consumer<User>() {
#Override
public void accept(User theUser) {
doSomethingWithUser(theUser);
}
});
The idea is that the doSomethingWithUser() method call will only be executed if the user is present. Your code executes the method call directly, and tries to pass its void result to ifPresent().
In addition to #JBNizet's answer, my general use case for ifPresent is to combine .isPresent() and .get():
Old way:
Optional opt = getIntOptional();
if(opt.isPresent()) {
Integer value = opt.get();
// do something with value
}
New way:
Optional opt = getIntOptional();
opt.ifPresent(value -> {
// do something with value
})
This, to me, is more intuitive.
Why write complicated code when you could make it simple?
Indeed, if you are absolutely going to use the Optional class, the most simple code is what you have already written ...
if (user.isPresent())
{
doSomethingWithUser(user.get());
}
This code has the advantages of being
readable
easy to debug (breakpoint)
not tricky
Just because Oracle has added the Optional class in Java 8 doesn't mean that this class must be used in all situation.
You can use method reference like this:
user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser);
Method ifPresent() get Consumer object as a paremeter and (from JavaDoc): "If a value is present, invoke the specified consumer with the value." Value it is your variable user.
Or if this method doSomethingWithUser is in the User class and it is not static, you can use method reference like this:
user.ifPresent(this::doSomethingWithUser);
Use flatMap. If a value is present, flatMap returns a sequential Stream containing only that value, otherwise returns an empty Stream. So there is no need to use ifPresent() . Example:
list.stream().map(data -> data.getSomeValue).map(this::getOptinalValue).flatMap(Optional::stream).collect(Collectors.toList());