如何从嵌套的 String 数组的 ArrayList 中删除相交的 String[] 数组?

How to remove intersecting String[] arrays from a nested ArrayList of String arrays?

假设我有一个 ArrayList<ArrayList<String[]>> 名为 ListToProcess 的变量,在每个 arrayList 中我有以下 ArrayLists of String[]:

    String[] arr1 = {"1","2","3"};
    String[] arr2 = {"7","5","3"};
    String[] arr3 = {"8","2","6"};
    String[] arr4 = {"0","4","9"};

ArrayList<String[]> arrString1 包含 arr1arr2 并且 ArrayList<String[]> arrString1 包含 arr3arr4 我想以这样的方式处理 ListToProcess 以删除 arr2 & arr3 因为与 arr1 相交(或保留 arr2 并删除 arr1arr3...) 从它。 我尝试通过以下方法将 ListToProcess 展平为 List<String[]> 并删除相交的元素 removeIntersectingArrays

    List<String[]> flatList =
            partitionsOfClustersIds.stream()
                    .flatMap(ListToProcess::stream)
                    .collect(Collectors.toList());
    ArrayList<String[]> flattenedArrayElements=  new ArrayList<String[]>(flatList);
    flattenedArrayElements= removeIntersectingArrays(flattenedArrayElements);

removeIntersectingArrays方法如下:

Public static ArrayList<String[]> removeIntersectingArrays(ArrayList<String[]> totalArrays) {
        List<Integer> idx = new ArrayList<Integer>();
        for (int i = 0; i < totalArrays.size(); i++)
            for (int j = i + 1; j < totalArrays.size(); j++) {
                String[] tmpArr = totalArrays.get(j);
                if (Arrays.stream(totalArrays.get(i)).distinct().filter(x -> Arrays.stream(tmpArr).anyMatch(y -> y.equals(x))).toArray().length != 0) {

                    idx.add(j);
                }
            }
        Collections.reverse(idx);
        for (int k : idx)
            totalArrays.remove(k); // this line raises an indexOutOfBound exception
        return totalArrays;
    }

但是我收到 indexOutOfBound 错误,知道如何解决这个问题吗?

不要使用具体实现(如ArrayList而不是抽象(如List)当它不给你买任何东西的时候。通常是这种情况,唯一的例外是当您需要能够调用未在 List 接口中定义并且只能通过 ArrayList class 访问的方法时,例如 ensureCapacity()trimToSize().

旁注:

  • Collectors.toList() 默认使用 ArrayList 作为 List 接口的实现;
  • 每当您需要具体实施时使用Collector.toCollection()

removeIntersectingArrays() 方法的时间复杂度通过维护一个 HashSet 来降低,该 HashSet 存储之前遇到的所有数组中的字符串。每个数组都必须根据这个集合进行检查。

    public static void main(String[] args) {
        List<List<String[]>> list= List.of(
                List.of(new String[]{"1","2","3"},
                        new String[]{"7","5","3"}),
                List.of(new String[]{"8","2","6"},
                        new String[]{"0","4","9"})
        );

        List<String[]> flatList = flatten(list);

        for (String[] arr: removeIntersectingArrays(flatList)) {
            System.out.println(Arrays.toString(arr));
        }
    }
    public static List<String[]> flatten(List<List<String[]>> source) {
        return source.stream()
                .flatMap(List::stream)
                .collect(Collectors.toList());
    }
    public static List<String[]> removeIntersectingArrays(List<String[]> source) {
        List<String[]> result = new ArrayList<>();
        Set<String> seen = new HashSet<>();
        for (String[] arr: source) {
            boolean notSeenPreviously = true;
            for (String next: arr) {
                if (seen.contains(next)) {
                    notSeenPreviously = false;
                    break;
                }
            }
            if (notSeenPreviously) {
                result.add(arr);
                Collections.addAll(seen, arr);
            }
        }
        return result;
    }

输出arr2 & arr3 被移除)

[1, 2, 3]
[0, 4, 9]

我发现从要删除的元素的索引列表中删除重复项解决了这个问题:这样做:

        ...
        // remove duplicates
        List<Integer> idxWithoutDuplicates = new ArrayList<>(
                new LinkedHashSet<>(idx));
        Collections.reverse(idxWithoutDuplicates); ...

解决了我的问题。

UPDATE:或其他解决方案是:检查索引是否已通过例如此衬里添加到上面的 idx 数组中:

...
if (!Arrays.asList(idx).contains(j))
    idx.add(j);...