1

I wanted to find an intersection between two arraylist that are of byte[] format and return the common indices. I have the code as follows and it works correctly:

ArrayList<Integer> intersect = new ArrayList<Integer>();
for(int j = 0; j < A.size(); j++)
    {
        byte [] t = A.get(j); 
        for (int j1 = 0; j1 < B.size(); j1++)
        {
            byte[] t1 = B.get(j1);
            if (Arrays.equals(t, t1))
            {
                intersect.add(j);
                break;
            }
        }
    }

However, as you can see, I have to use two for loops. Is there any way I can do it without using any for loops? I have tried to use "retainAll" but for some reason, it kept giving me an empty array. What can be the possible reason for that?

Bikas
  • 23
  • 1
  • 8
  • 2
    _I have tried to use "retainAll" but for some reason, it kept giving me an empty array. What can be the possible reason for that?_ Because the implementation of `equals()` for arrays checks for identity, not contents. – Sean Bright Jun 20 '18 at 20:22
  • https://stackoverflow.com/questions/5283047/intersection-and-union-of-arraylists-in-java might provide some useful information using other collection types to get the same behavior. – Stephan Jun 20 '18 at 20:23
  • @Shahnewaz Given that you need control over the equality check, the code you are using is probably the best you can do without another data structure. Also, given that you are trying to "retain" the position of the array in the list (and not the array itself), `retainsAll()` would never have given you the result you were looking for. – Sean Bright Jun 20 '18 at 20:39
  • Possible duplicate of [Intersection and union of ArrayLists in Java](https://stackoverflow.com/questions/5283047/intersection-and-union-of-arraylists-in-java) – Chisko Jun 20 '18 at 20:41
  • @Chisko eh... not _really_. The concept is the same, but the accepted answer is not going to work. – Sean Bright Jun 20 '18 at 20:43
  • @SeanBright what about any of the other 5-10 answers? – Chisko Jun 20 '18 at 20:45
  • @Chisko I'm not sure. Do any of them call `Arrays.equals()?` If not, then I doubt it. – Sean Bright Jun 20 '18 at 20:45

3 Answers3

0

If you just dont want to use for loops, you may try the Java 8 streams, since you have not shared the complete code I did not try it out.

List<T> intersect = list1.stream()
.filter(list2::contains)
.collect(Collectors.toList());
Jeeppp
  • 1,553
  • 3
  • 17
  • 39
  • 1
    So, for my list it should be List intersect = A.stream().filter(B::contains).collect(Collectors.toList()); Right? – Bikas Jun 20 '18 at 20:29
  • @SeanBright Why on earth it ***should*** work for ` = Array `if the OP is not even asking for that?!!! – Yahya Jun 20 '18 at 20:48
  • @SeanBright You are right... OP's question is very bad! – Yahya Jun 20 '18 at 20:51
0

I think for T your solution with brutforce is not so bad. This is a small refactoring of it. Yes, for specific T (e.g. int) you could use special structures, but in general case, I think this is not implementable.

public static <T> List<Integer> intersect(List<T> A, List<T> B, BiPredicate<T, T> isEqual) {
    List<Integer> intersect = new LinkedList<>();
    int i = -1;

    for (T a : A) {
        i++;

        if (B.stream().anyMatch(b -> isEqual.test(a, b)))
            intersect.add(i);
    }

    return intersect;
}

Client code could look like:

List<byte[]> a = Collections.emptyList();
List<byte[]> b = Collections.emptyList();
List<Integer> intersect = intersect(a, b, Arrays::equals);
Oleg Cherednik
  • 17,377
  • 4
  • 21
  • 35
-1

This may help:

public <T> List<T> intersection(List<T> list1, List<T> list2) {
        List<T> list = new ArrayList<T>();

        for (T t : list1) {
            if(list2.contains(t)) {
                list.add(t);
            }
        }
        return list;
    }

Reference: Intersection and union of ArrayLists in Java

Sai
  • 1