如何在特定位置将一个ArrayList中多个项与另一个ArrayList进行比较?

5

背景:有一个产品列表页面,我需要获取所有产品的名称(包括缺货的产品),然后验证所有缺货的产品是否在最后。

问题:我已经浏览了所有页面并将产品名称存储在ArrayList中。

假设list1及其内容为-

[instant bcaa, vegan bcaa, complete bcaa energy™, branched chain amino acid (bcaa) tablets 1000mg, endure™, branched chain amino acids (bcaa), instant leucine, leucine tablets 1000mg, complete intra-workout™, leucine, bcaa jelly mix, complete hydration drink™, informed bcaa™, instant bcaa cocktail bundle]

现在我有另一个列表,其中只包含缺货产品。 list2和其内容如下 -
[informed bcaa™, instant bcaa cocktail bundle]

我必须确保list1是否以相同的顺序在末尾包含了所有的list2项


假设列表没有重复项(每个都是唯一的):找到两个列表中都存在的所有元素(例如使用retainAll());删除所有这些元素(removeAll),然后将它们再次添加到末尾(addAll())-最好使用第一个列表的副本。或者,可以像流一样操作:对于列表2中的每个元素,如果它也在列表1中,则从列表1中删除它并将其添加到列表1的末尾... - user85421
5个回答

4
这个问题本质上是想要验证给定的列表 A 是否以第二个列表 B 结尾。你可以通过确定列表 B 的长度,从列表 A 的末尾回溯相同的距离,然后对两个列表进行成对比较来实现此目的。
public static boolean listEndsWith(List<?> A, List<?> B) {
    if (B.size() > A.size()) {
        return false;
    }

    for (int i = A.size() - B.size(), j = 0; i < A.size(); i++, j++) {
        if (!A.get(i).equals(B.get(j))) {
            return false;
        }
    }

    return true;
}

3
在Java 8+中,你可以使用stream().skip()跳过前面的list1.size() - list2.size()个对象,然后与list2进行比较。
    if (list1.size() > list2.size()) {
        AtomicInteger ordinal = new AtomicInteger(0);
        boolean matched = list1.stream().skip(list1.size() - list2.size())
                .allMatch(item -> item == list2.get(ordinal.getAndIncrement()));

        System.out.println(matched);
    }

2
生成一个新的列表,该列表是 list1 的最后 n 个元素,其中 n 是 list2 的长度。然后将 list3 与 list1 进行比较。
第三个列表可以这样传递:
ArrayList list3 = new ArrayList(list1.subList(list1.size() - list2.size(), list2.size())

1
不错的想法,但是如果list2list1长,这将抛出一个IndexOutOfBoundsException异常,所以你需要先检查一下。 - nbrooks
是的,你说得对。在那方面上我更喜欢你的方法。 - Jonathan Wilson

1
为了检查list1是否从特定位置包含list2,您可以使用以下函数:
 public static boolean compareArrsFromPosition(List<?> list1, List<?> list2, int fromPosition) {
    if (list1.size()-fromPosition < list2.size()) return false;
    return list1.subList(fromPosition,fromPosition+list2.size()).equals(list2);
}

要检查list1的结尾,您可以这样调用:

compareArrsFromPosition(list1, list2, list1.size()-list2.size());

你可以将其作为单个语句完成,return list1.size()-fromPosition >= list2.size() && list1.subList(fromPosition,fromPosition+list2.size()).equals(list2); - Holger

1

或者,您可以反转您的两个List(虽然可能需要空间来存储副本,但是时间复杂度为线性),并根据列表B的大小进行迭代匹配所有元素(假设它的大小较小):

public static boolean listEndsWith(List<?> A, List<?> B) {
    Collections.reverse(B); // modifies B, so you can choose to clone and reverse
    Collections.reverse(A);
    return IntStream.range(0, B.size())
            .allMatch(i -> A.get(i).equals(B.get(i)));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接