Confusion in functioning of Lambda expression

I am trying to learn lambda expressions. I am currently referring to OCP study guide.

In one example of lambda expression there is a Animal class and another another interface called CheckTrait. The functioning of lambda expression is very confusing for me. Example code is as shown below:

Without lambda expression.

public interface CheckTrait {
    public boolean test(Animal a);
}


public class Animal  implements CheckTrait{

    private String species;
    private boolean canHop;
    private boolean canSwim;

    public Animal(String species, boolean canHop, boolean canSwim) {
        super();
        this.species = species;
        this.canHop = canHop;
        this.canSwim = canSwim;
    }

    public boolean canHop() {
        return this.canHop;
    }

    public String toString() {
        return species;
    }

    public boolean canSwim() {
        return this.canSwim;
    }

    @Override
    public boolean test(Animal a) {

        return a.canHop();
    }
}

    public class FindMathcingAnimals {

    private static void print(Animal animal, CheckTrait trait) {
        if(trait.test(animal)){
            System.out.println(animal+" can hop" );
        }else {
            System.out.println(animal+" cannot hop");
        }

    }

    public static void main(String[] args) {

        Animal animal2= new Animal("Kangaroo", true, false);    
        print(animal2,animal2);
    }

}

When we run the above class we get the output as Kangaroo can hop

With lambda expression

public interface CheckTrait {
    public boolean test(Animal a);
}


public class Animal  {

    private String species;
    private boolean canHop;
    private boolean canSwim;

    public Animal(String species, boolean canHop, boolean canSwim) {
        super();
        this.species = species;
        this.canHop = canHop;
        this.canSwim = canSwim;
    }

    public boolean canHop() {
        return this.canHop;
    }

    public String toString() {
        return species;
    }

    public boolean canSwim() {
        return this.canSwim;
    }


}


public class FindMathcingAnimals {

    private static void print(Animal animal, CheckTrait trait) {
        if(trait.test(animal)){
            System.out.println(animal+" can hop" );
        }else {
            System.out.println(animal+" cannot hop");
        }

    }

    public static void main(String[] args) {

        Animal animal2= new Animal("Kangaroo", true, false);    
        print(animal2,s->s.canHop());
    }

}

My Question is, In the below line
print(animal2,s->s.canHop());

I am not passing any value to s but just an expression, then how is the program computing the result? I am aware that it is taking the animal object and checking the canhop variable just by intuition,but I am not understanding the logic here. Kindly provide your thoughts.

Edit: based on Aominè’s answer:

So, can i conclude that.
In the print method I am passing the behavior for CheckTrait, and in the print method can be reduced as:

step1: if(trait.test(animal)){

step2: if(s.canHop())

step3: if(animal.canHop)

the above steps are just for my understanding.

Solution:

I am not passing any value to s but just an expression, then how is
the program computing the result?

below you pass in a behaviour (a function) as the second argument to the print method which will be used within the print method.

print(animal2, s -> s.canHop());

this function reads as “given an element say s, call the canHop() method on the element”

now within the print method when you do:

if(trait.test(animal)){ ... }

you’re calling trait.test(animal) and passing the animal object to the function we passed in, we then apply the function to the input animal.

if it helps this:

print(animal2,s -> s.canHop());

can be seen as being the same as:

print(animal2, new CheckTrait() {
       @Override
     public boolean test(Animal s) {
           return s.canHop();
     }
});

edit:

as you’ve mentioned the method calls can be seen as:

if(trait.test(animal)){..} -> if(s.canHop()){..} -> if(animal.canHop){..} // pseudocode

How to get Item from set based on parameter using Java8 features

I have a set with below items

Set<String> formatLookup = new HashSet<>();
formatLookup.add("DHMdhm");
formatLookup.add("THMthm");
formatLookup.add("JHMjhm");

and I am passing one String as below

String filterVal = "THM";

Now I want to check the filter value is present in which index of the set (the filter value order may vary like THM,HTM,MHT etc) and I want to return that item from set. Below is the code for this and it’s working.

private static String getStoredFilter(String filterVal) {
    String format = "DHMdhm";
    boolean found = false;
    Set<String> formatLookup = new HashSet<>();
    formatLookup.add("DHMdhm");
    formatLookup.add("THMthm");
    formatLookup.add("JHMjhm");
    Iterator<String> setIterator = formatLookup.iterator();
    while (setIterator.hasNext()) {
        String fmt = setIterator.next();
        for (int j = 0; j < filterVal.length(); j++) {
            if (!(fmt).contains(String.valueOf(filterVal.charAt(j)))) {
                found = false;
                break;
            } else {
            found = true;
            }
        }
        if (found) {
            return fmt;
        }
    }
    return null;
}

I want to use Java8 features. I am new to Java8 and I tried with stream and foreach. But, since foreach can’t return a value so I am not sure how to get this done.

Could you help me on this?

Solution:

You can handle permutations by simply bringing both, keys and input, into a canonical permutation, e.g. just sort them:

static String canonical(String s) {
    char[] c = s.toCharArray();
    Arrays.sort(c);
    return String.valueOf(c);
}

Prepare a map from canonical key to specified string

// do this only once
private static final Map<String,String> formatLookup
    = Stream.of("DHMdhm", "THMthm", "JHMjhm")
            .collect(Collectors.toMap(s -> canonical(s), Function.identity()));

and the actual operation

private static String getStoredFilter(String filterVal) {
    String key = canonical(filterVal);

    // check whether there's an exact match
    String quickChecked = formatLookup.get(key);
    if(quickChecked!=null) return quickChecked;

    // search for substring matches
    return formatLookup.entrySet().stream()
        .filter(e -> e.getKey().contains(key))
        .map(Map.Entry::getValue)
        .findAny().orElse(null);
}

If the strings may contain duplicate characters and you want to handle that, you only have to change the canonical method, e.g.

static String canonical(String s) {
    return s.codePoints().collect(BitSet::new, BitSet::set, BitSet::or).stream()
        .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
        .toString();
}

Replace lambda with method reference in flatMap during array mapping

Say we have a Customer class:

public class Customer {
    private Car[] cars;
    // getter, setter, constructor
}

and collection of customers which we need to map on cars.

Currently I’m doing it somehow like this:

Collection<Customer> customers = ...
customers.stream().flatMap(
        customer -> Arrays.stream(customer.getCars())
)...

It works well, but the code doesn’t look elegant. I’d really like to replace it with code that uses method references which usually looks more readable and more compact. But using a field of array type makes it hard.

Question: is there any way of enhancing the flatMap call so it will be more readable/compact/clear?

Solution:

You can split the flatMap call into two calls – map and flatMap – each receiving a method reference:

Collection<Customer> customers = ...
customers.stream()
         .map(Customer::getCars)
         .flatMap(Arrays::stream)...

How to convert list without generics to list with generics using streams in java?

I would like convert a List without generics to List<MyConcreteType>.

I also need to filter out only my concrete types.

My current stream logic is like:

List list = new ArrayList();
Object collect1 = list.stream().filter((o -> o instanceof MyConcreteType)).collect(Collectors.toList());

But as a result I’m getting an Object instead of a List. Is there a way to convert this Stream to a List<MyConcreteType>?

Solution:

Use parameterized types instead of raw types, and use map to cast the objects that pass the filter to MyConcreteType:

List<?> list = new ArrayList();
List<MyConcreteType> collect1 = 
    list.stream()
        .filter((o -> o instanceof MyConcreteType))
        .map(s-> (MyConcreteType) s)
        .collect(Collectors.toList());

or (similar to what Boris suggested in comment):

 List<?> list = new ArrayList();
 List<MyConcreteType> collect1 = 
     list.stream()
         .filter(MyConcreteType.class::isInstance)
         .map(MyConcreteType.class::cast)
         .collect(Collectors.toList());

NullPointerException: element cannot be mapped to a null key

I have read the topic:

Collectors.groupingBy doesn’t accept null keys

But I don’t understand how can I apply it for my issue:

my code:

Map<String, List<MappingEntry>> mappingEntryMap = mapping.getMappingEntries()
                .stream()
                .collect(Collectors.groupingBy(MappingEntry::getMilestone, Collectors.mapping(e -> e, Collectors.toList())));

For me MappingEntry::getMilestone sometimes can return null. It is ok for my situation but I see:

Caused by: java.lang.NullPointerException: element cannot be mapped to a null key
    at java.util.Objects.requireNonNull(Objects.java:228)
    at java.util.stream.Collectors.lambda$groupingBy$45(Collectors.java:907)
    at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

How can I avoid this exception?

Solution:

Use Collectors.toMap instead and specify that a HashMap is used (as it allows one null key)

 Collectors.toMap(
       MappingEntry::getMilestone,
       x -> {
           List<MappingEntry> list = new ArrayList<>();
           list.add(x);
           return list;
       },
       (left, right) -> {
            left.addAll(right);
            return left;
       },
       HashMap::new

)

Can I count my stream size if I limit it by a predicate dependent on the input?

I want to make a stream with random numbers. As soon as the numbers fullfill a certain condition I want to now how many iterations was needed.
So either I want to have the size of the stream or an Collection from which I can read then the size.

Here are my approaches:

random.ints(0, Integer.MAX_VALUE).anyMatch(a -> {return a < 20000;});

This gives me only the a boolean as soon as my condition is fullfilled.

random.ints(0, Integer.MAX_VALUE).filter(a -> a < 20000).limit(1).count();

And this returns obviously 1. But I want to have the size before I filtered my result. I further tried several things with a counting variable but since lambdas are capturing them effectifely final from outside I have an initialising problem.

Any help or hint is appreciated

Solution:

Java 9 has a feature to support that – takeWhile:

random.ints(0, Integer.MAX_VALUE).takeWhile(a -> a < 20000).count();

Java 8 lambda expression with an abstract class having only one method

I’m learning lambda expressions in Java 8. Can somebody explain to me how to use lambda expression with an abstract class having only one method (if it’s possible)?

For example, this is the abstract class:

public abstract class ClassA {

    public abstract void action();

}

And I have another class that take’s in its constructor an instance of ClassA:

public ClassB {
   public ClassB(String text, ClassA a){
      //Do stuff
    }
}

So I was wondering how to write something like this:

ClassB b = new ClassB("Example", new ClassA(() -> System.out.println("Hello")));

Obviously that statement doesn’t work, but is there a way to use a lambda expression here or not? If there is, what am I doing wrong?

Solution:

No, you cannot achieve this because ClassA must be a functional interface. A functional interface is an interface that contains exactly one abstract method. It may contain zero or more default methods and/or static methods in addition to the abstract method. Because a functional interface contains exactly one abstract method, you can omit the name of that method when you implement it using a lambda expression. For example, consider the following interface:

interface Predicate<T> {
    boolean test(T t);
}

The purpose of this interface is to provide a method that operates on an object of class T and return a boolean. You could have a method that takes an instance of class that implements this interface defined like this:

public void printImportantData(ArrayList<Data> dataList, Predicate<Data> p) {
    for (Data d : dataList) {
        if (p.test(d)) {
            System.out.println(d);
        }
    }
}

where Data class could be as simple as:

public class Data {
    public int value;
}

Now, you can call the above method as follows:

 printImportantData(al, (Data d) -> { return d.value > 1; }); 

Notice the method does not have a name here. This is possible because the interface has only one abstract method so the compiler can figure out the name. This can be shortened to:

printImportantData(al, (Data d) -> d.value > 1);

Notice that here are no curly brackets and no return keyword. This is possible because the method returns a boolean and the expression d.value > 1 also returns a boolean. The compiler is therefore able to figure out that the value of this expression is to be returned from the method. This can be shortened even more to:

printImportantData(al, d -> d.value > 1);

Notice that there is no type declaration of d! The compiler can figure out all information it needs because the interface has only one abstract method and that method has only one parameter. So you don’t need to write all those things in your code.
Compare the above approach to the old Java 7 style using an inner class that does effectively the same thing:

printImportantData(al, new Predicate<Data>() {
    public boolean test(Data d) {
        return d.value > 1;
    }
});

Why does \R behave differently in regular expressions between Java 8 and Java 9?

The following code compiles in both Java 8 & 9, but behaves differently.

class Simple {
    static String sample = "\nEn un lugar\r\nde la Mancha\nde cuyo nombre\r\nno quiero acordame";

    public static void main(String args[]){
        String[] chunks = sample.split("\\R\\R");
        for (String chunk: chunks) {
            System.out.println("Chunk : "+chunk);
        }
    }
}

When I run it with Java 8 it returns:

Chunk : 
En un lugar
de la Mancha
de cuyo nombre
no quiero acordame

But when I run it with Java 9 the output is different:

Chunk : 
En un lugar
Chunk : de la Mancha
de cuyo nombre
Chunk : no quiero acordame

Why?

Solution:

It was a bug in Java 8 and it got fixed: JDK-8176029 : “Linebreak matcher is not equivalent to the pattern as stated in javadoc”.

Also see: Java-8 regex negative lookbehind with `\R`

Java 8 -Two interfaces contain same 'name' default method but different method signature, how to override?

I understand that if a class implements multiple interfaces containing default methods of same name, then we need to override that method in the child class so as to explicitly define what my method will do.
Problem is, see the below code :

interface A {
    default void print() {
        System.out.println(" In interface A ");
    }
}

interface B {
    default String print() {
        return "In interface B";
    }
}

public class C implements A, B {

    @Override
    public String print() {
        return "In class C";
    }

    public static void main(String arg[]) {
        // Other funny things
    }
}

Now interface A and B both have a default method with name ‘print’ but I want to override the print method of interface B – the one that returns a string and leave A’s print as is. But this code doesn’t compile giving this :

Overrides A.print
The return type is incompatible with A.print()

Clearly compiler is trying to override A’s print method, and I have no idea why !

Solution:

This is not possible.

8.4.8.3:

If a method declaration d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type-substitutable for d2, or a compile-time error occurs.

8.4.5:

A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2 iff any of the following is true:

  • If R1 is void then R2 is void.

  • If R1 is a primitive type then R2 is identical to R1.

  • If R1 is a reference type then one of the following is true:

    • R1, adapted to the type parameters of d2, is a subtype of R2.

    • R1 can be converted to a subtype of R2 by unchecked conversion.

    • d1 does not have the same signature as d2, and R1 = |R2|.

In other words, void, primitive- and reference-returning methods may only override and be overridden by methods of that same respective category. A void method may only override another void method, a reference-returning method may only override another reference-returning method, and so on.

One possible solution to the problem you’re having could be to use composition instead of inheritance:

class C {
    private A a = ...;
    private B b = ...;
    public A getA() { return a; }
    public B getB() { return b; }
}