1

I aimed to rework the code found here: https://stackoverflow.com/a/8995988 But this proved unsuccessful. I got an idea from here: https://www.logicbig.com/how-to/java/lambda-list-contains-a-substring.html

And my idea worked, but I suspect it is bad code and I'd like to know why the StackOverflow rework I did does not work as anticipated.

I'll present both bits of code in 1 block. Simply switch which "if" line is commented and not commented to go between the working and not working versions.

import java.util.Arrays;
import java.util.List;

public class Demo {
    public static void main(String[] args) {
        List<String> result0 = Arrays.asList("/Videos/Templates/file.mp4", "/Videos/Templates/file2.mp4", "/Videos/Templates/file3.mp4");
        List<String> result2 = Arrays.asList("/Videos/Templates/file.mp4.sha256");

        for (int i = 0; i < result0.size(); i++) {

            List<String> finalResult = result0;
            int finalI = i;
            // if (result2.parallelStream().anyMatch(x -> x.contains(finalResult.get(finalI)))) {
            if (result2.parallelStream().anyMatch(finalResult.get(finalI)::contains)){
                System.out.println("sha matches files: " + result0.get(i));
            }
        }
    }
}

If it proves that this question better serves as just a comment on https://stackoverflow.com/a/8995988 better explaining the code, then I'm happy to modify to that.

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
TelamonAegisthus
  • 267
  • 2
  • 11
  • I edited your question's code slightly. In addition to adding imports to make it compile (to make your question satisfy "reproducible" in "minimal, reproducible example"), I tweaked the style of the two `if` statements to remove extraneous differences between them, though without changing the behavior at all (to make your question satisfy "minimal" in "minimal, reproducible example"). – Joseph Sible-Reinstate Monica Jan 03 '20 at 04:16

2 Answers2

3

Because contains is not a commutative operator. For example, "lightning" contains "light", but "light" does not contain "lightning". In your case, "/Videos/Templates/file.mp4.sha256" contains "/Videos/Templates/file.mp4", but "/Videos/Templates/file.mp4" does not contain "/Videos/Templates/file.mp4.sha256".

(In case it isn't clear, foo::bar is equivalent to x -> foo.bar(x), so finalResult.get(finalI)::contains is equivalent to x -> finalResult.get(finalI).contains(x).)

1

@Joseph's right! You just inverted the order of the method's object and operand. The String.contains method is to be called on the Strings of the result2 Stream.

Moreover, you don't need to use any for loop to compute this result, both Lists can be converted into Streams, hence avoiding to mixing unnecessarily imperative and reactive styles on the same method.

Here is a Streams-only version of your program:

import java.util.Arrays;
import java.util.List;

public class Demo {
    public static void main(String[] args) {
        List<String> result0 = Arrays.asList("/Videos/Templates/file.mp4", "/Videos/Templates/file2.mp4", "/Videos/Templates/file3.mp4");
        List<String> result2 = Arrays.asList("/Videos/Templates/file.mp4.sha256");

        result0.parallelStream()
            .filter(item0 -> result2.parallelStream()
                                .anyMatch(item2 -> item2.contains(item0)))
            .forEach(item0 -> System.out.println("sha matches files: " + item0));

    }
}
dbaltor
  • 2,737
  • 3
  • 24
  • 36