如何在java中删除arraylist中的重复字符串数组,同时忽略第一个索引

yqyhoc1h  于 2021-06-29  发布在  Java
关注(0)|答案(4)|浏览(335)

假设我有一个 ArrayList<String[]> 像这样:

ArrayList<String[]> arrayList = new ArrayList<>();
arrayList.add(new String[]{"1", "hello", "goodbye"});
arrayList.add(new String[]{"2", "car", "goodbye"});
arrayList.add(new String[]{"3", "jack", "goodbye"});
arrayList.add(new String[]{"4", "mcdonalds", "goodbye"});
arrayList.add(new String[]{"5", "hello", "goodbye"});
[[1, hello, goodbye], [2, car, goodbye], [3, jack, goodbye],
 [4, mcdonalds, goodbye], [5, hello, goodbye]]

如何在不考虑第一个索引的情况下,编写一个函数来删除arraylist中重复的字符串数组?”在这种情况下,“复制”是:第一个和最后一个元素

[1, hello, goodbye], [5, hello, goodbye]

生成的arraylist将是:

[[1, hello, goodbye], [2, car, goodbye], [3, jack, goodbye],
 [4, mcdonalds, goodbye]]

我可以想出一种非常复杂的方法,将整个列表克隆到一个temp变量,然后将原始列表中的所有值设置为“dummy”。从那里第一个索引是标准化的,您可以在数组之间进行比较。然后您可以排列重复项的索引,并将它们从原始项中删除。不过,这似乎效率非常低,对大数据集来说也不好。

igsr9ssn

igsr9ssn1#

假设 strings 不是预定义的,顺序很重要,可以使用 Set<List<String>> 具体如下:
迭代 ArrayList 元素并获得 List<String> 表示它的字符串(没有第一个),如果它不在集合中,则添加它,并在迭代时将数组添加到结果列表中:

List<String[]> arrayList = new ArrayList<>();
arrayList.add(new String[]{"1", "hello", "goodbye"});
arrayList.add(new String[]{"2", "car", "goodbye"});
arrayList.add(new String[]{"3", "jack", "goodbye"});
arrayList.add(new String[]{"4", "mcdonalds", "goodbye"});
arrayList.add(new String[]{"5", "hello", "goodbye"});

Set<List<String>> set = new HashSet<>();
List<String[]> res = new ArrayList<>();
for(String[] arr : arrayList) {
     List<String> current = Arrays.asList(Arrays.copyOfRange(arr, 1, arr.length));
     if(!set.contains(current)) {
          res.add(arr);
          set.add(current);
     }
}

for(String[] arr : res)
     System.out.println(Arrays.toString(arr));

输出:

[1, hello, goodbye]
[2, car, goodbye]
[3, jack, goodbye]
[4, mcdonalds, goodbye]
swvgeqrz

swvgeqrz2#

您应该首先创建一个类:(它更可读,但当然可以只使用索引,比如arraylist[0]=index,arraylist[1]=message1…等等)

public class yourClass {
    Integer index;
    String message1;
    String message2;
    yourClass(Integer a, String b, String c){
        index = a;
        message1 = b;
        message2=c;
    }
}

那么您可以简单地使用for/foreach

class Main {

    public static void main(String[] args) {
    // write your code here
        ArrayList<yourClass> arrayList = new ArrayList<>();
        yourClass a = new yourClass(1,"hello","goodbye");
        yourClass b = new yourClass(2,"hello","goodbye");
        yourClass c = new yourClass(3,"hello","goodbye");
        yourClass d = new yourClass(4,"helloooooooooooo","goodbyeeeeeeeeee");
        yourClass e = new yourClass(5,"helloo","hellooo");
        arrayList.add(a);
        arrayList.add(b);
        arrayList.add(c);
        arrayList.add(d);
        arrayList.add(e);
        arrayList.forEach(el->{
            arrayList.forEach(el2->{
                if((el.message2 == el2.message2) && (el.message1 == el2.message1)){
                    arrayList.remove(el.index);
                }
            });
        });
        System.out.println((arrayList));
    }
}

或者如果您擅长流,这也是一个很好的解决方案,请参阅this:https://www.techiedelight.com/remove-elements-list-satisfies-predicate-java/

eqzww0vc

eqzww0vc3#

好吧,你可以把它们添加到集合中,让集合来完成工作。

List<String[]> arrayList = new ArrayList<>();
arrayList.add(new String[] { "1", "hello", "goodbye" });
arrayList.add(new String[] { "2", "car", "goodbye" });
arrayList.add(new String[] { "3", "jack", "goodbye" });
arrayList.add(new String[] { "4", "mcdonalds", "goodbye" });
arrayList.add(new String[] { "5", "hello", "goodbye" });

Comparator<String[]> comp =
        Comparator.comparing((String[] arr) -> arr[1])
                .thenComparing(arr -> arr[2]);

Set<String[]> set = new TreeSet<>(comp);
set.addAll(arrayList);
set.forEach(arr->System.out.println(Arrays.toString(arr)));

印刷品

[2, car, goodbye]
[1, hello, goodbye]
[3, jack, goodbye]
[4, mcdonalds, goodbye]

您可以将它们保留在集合中,也可以将它们添加到数组列表中。
如果这里有一个通用的解决方案,可以让你选择任何一组你想要过滤的索引。
首先创建一个helper方法来构建 predicate 。它维护一个集合来检测以前看到的元素。

public static Predicate<String[]> using(int... i) {
    Set<String> seen = ConcurrentHashSet.newKeySet();
    return e -> seen.add(Arrays.stream(i).mapToObj(r -> e[r])
        .collect(Collectors.joining("")));
}

然后,只需过滤调用该方法的值即可生成 predicate 。

arrayList = arrayList.stream().filter(using(1,2))
                .collect(Collectors.toList());

arrayList.forEach(
        arr -> System.out.println(Arrays.toString(arr)));

印刷品

[1, hello, goodbye]
[2, car, goodbye]
[3, jack, goodbye]
[4, mcdonalds, goodbye]
exdqitrt

exdqitrt4#

你可以使用 TreeSet 使用自定义比较器从列表中排除重复项,通过字符串数组的第二列和第三列进行比较。但不能保证元素的顺序保持不变。如果有关系,您可以按第一列对它们进行排序,或者将它们加载到其他列表中,然后检查此列表是否正确 contains 第一个列表中的元素:

List<String[]> list1 = Arrays.asList(
        new String[]{"1", "hello", "goodbye"},
        new String[]{"2", "car", "goodbye"},
        new String[]{"3", "jack", "goodbye"},
        new String[]{"4", "mcdonalds", "goodbye"},
        new String[]{"5", "hello", "goodbye"});

TreeSet<String[]> treeSet =
        new TreeSet<>(Comparator.comparing(arr -> arr[1] + arr[2]));

treeSet.addAll(list1);
treeSet.stream().map(Arrays::toString).forEach(System.out::println);
// [2, car, goodbye]
// [1, hello, goodbye]
// [3, jack, goodbye]
// [4, mcdonalds, goodbye]

按第一列排序:

List<String[]> list2 = treeSet.stream()
        .sorted(Comparator.comparing(arr -> arr[0]))
        .collect(Collectors.toList());

加载到另一个列表并检查此列表 contains 第一个列表中的元素:

List<String[]> listSet = new ArrayList<>(treeSet);

List<String[]> list2 = list1.stream()
        .filter(listSet::contains)
        .collect(Collectors.toList());
list2.stream().map(Arrays::toString).forEach(System.out::println);
// [1, hello, goodbye]
// [2, car, goodbye]
// [3, jack, goodbye]
// [4, mcdonalds, goodbye]

另请参阅:如何有效地查找数组中的重复元素?

相关问题