snowflake
snowflake

Reputation: 89

Java 8 Stream operation based on lists

i have two list. First one is list of string - A list, the second one contains list of new class, lets say B class.

The B class contains String fields like example1,example2,example3,example4 and many more.

I tried something like this but I think its working on clone collection and not changing particular value to null.

listOfB.stream().flatMap(p -> Stream.of(p.getExample1(),p.getExample2(), 
p.getExample3(), p.getExample4()))
            .forEach(i -> {
                if (listOfA.contains(i)) {
                    i = null
                }
            });

what i want to achieve is to stream over the List of B objects, get all example fields (from 1 to 4) and then check if A list contains at least one of example fields value, if yes then set this particular example field to null.

Upvotes: 0

Views: 1316

Answers (3)

Hadi
Hadi

Reputation: 17299

You can do it something like this: use set instead of list

bList = bList.stream().map(b -> b.modify(aSet))
            .collect(Collectors.toList());

OR

bList.replaceAll(b -> b.modify(aSet));

and define a method in B class:

public B modify(Set<String> set) {
    this.example1 = set.contains(this.example1) ? null : this.example1;
    this.example2 = set.contains(this.example2) ? null : this.example2;
    this.example3 = set.contains(this.example3) ? null : this.example3;
    this.example4 = set.contains(this.example4) ? null : this.example4;
    return this;
}

Upvotes: 0

Vincent Passau
Vincent Passau

Reputation: 822

To perform this with only one stream you must pass by a series of if checks inside your lambda.

public void stack() {
    List<String> aList = Arrays.asList("foo2", "baz4");

    B b1 = new B("foo1", "foo2", "foo3", "foo4");
    B b2 = new B("bar1", "bar2", "bar3", "bar4");
    B b3 = new B("baz1", "baz2", "baz3", "baz4");

    List<B> bList = Stream.of(b1, b2, b3).peek(b -> {
        if (aList.contains(b.getExample1())) {
            b.setExample1(null);
        }
        if (aList.contains(b.getExample2())) {
            b.setExample2(null);
        }
        if (aList.contains(b.getExample3())) {
            b.setExample3(null);
        }
        if (aList.contains(b.getExample4())) {
            b.setExample4(null);
        }
    }).collect(Collectors.toList());

    System.out.println(bList);
}

Output :

B [example1=foo1, example2=null, example3=foo3, example4=foo4],

B [example1=bar1, example2=bar2, example3=bar3, example4=bar4],

B [example1=baz1, example2=baz2, example3=baz3, example4=null]

Upvotes: 1

mattmess1221
mattmess1221

Reputation: 4454

Changing lambda parameters have no effect outside the lambda. The method you're looking for is .filter()

.filter(i -> !listOfA.contains(i))

Though replacing forEach with filter won't do much because filter is not a terminal operation. Notice how it returns Stream<T>. If you want the changes to take effect in listOfB, you need to collect the stream into a new list and reassign it.

List<String> list = stream.collect(Collectors.toList())

Upvotes: 0

Related Questions