Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 streams how to filter contents a List not found in another arrayList?

Tags:

java

java-8

Can I filter an array list based on the elements found in another array list in java 8? The whole story is that I have fetched list of active employees from oracle E-business suite app

**EmpID**
00123
003456
023299  

and I have a separate file which contains photo with file Name EmpID.jpeg

**FileName**
00123.jpeg
003456.jpeg
023299.jpeg         

Now my purpose is to compare the lists and to filter employees who provide me photos and from those they did not give me.

private ArrayList<String> _IDsFromFile;
private ArrayList<String> _IDsFromImage;

      ---
      ---

public void compareAndCopy(String fileName){

}
like image 359
Clickmit Wg Avatar asked Mar 11 '17 02:03

Clickmit Wg


2 Answers

You can use filter API in java 8 Stream to do it. Like the following code snippet:

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Shizhz
 */
public class Main {
    private static Set<String> _IDsFromFile;
    private static Set<String> _IDsFromImage;

    static {
        _IDsFromFile = new HashSet();
        _IDsFromFile.add("00123");
        _IDsFromFile.add("003456");
        _IDsFromFile.add("023299");
        _IDsFromFile.add("023300");

        _IDsFromImage = new HashSet<>();
        _IDsFromImage.add("00123.jpeg");
        _IDsFromImage.add("003456.jpeg");
        _IDsFromImage.add("023299.jpeg");
    }

    private static Set<String> filterEmployeesWithPhones(Set<String> employeeSet, Set<String> photoSet) {
        return employeeSet.stream().filter(empId -> photoSet.contains(empId + ".jpeg")).collect(Collectors.toSet());
    }

    public static void main(String[] args) {
        filterEmployeesWithPhones(_IDsFromFile, _IDsFromImage).forEach(emp -> System.out.println(emp));
    }
}

will give you the result:

00123

003456

023299

like image 28
shizhz Avatar answered Oct 06 '22 01:10

shizhz


First of all, you should convert one or the other of these lists into a Set, so that the .contains() check is efficient. Calling .contains() on a List is a linear-time operation, meaning doing so n times is quadratic.

Once you've done that it's straightforward to use .filter() or even .partitioningBy() to determine where the two lists overlap.

Set<String> imageIdsSet = new HashSet<>(IDsFromImage);

List<String> overlappingIds = IDsFromFile.stream()
    .filter(imageIdsSet::contains)
    .collect(toList());

// OR

Map<Boolean, List<String>> partitionedIds = IDsFromFile.stream()
    .collect(partitioningBy(imageIdsSet::contains));
List<String> overlappingIds = partitionedIds.get(true);
List<String> missingIds = partitionedIds.get(false);

What you're describing, in principle, are set operations. The "overlapping" IDs are the intersection of the two sets of IDs, while the "missing" IDs are the difference.

Guava provides efficient implementations of these operations in their Sets utility. (union, intersection, difference, and complementOf).

like image 194
dimo414 Avatar answered Oct 06 '22 01:10

dimo414