如何从Java列表中删除重复项

Posted

技术标签:

【中文标题】如何从Java列表中删除重复项【英文标题】:How to remove duplicates from Set of list in Java 【发布时间】:2021-12-13 14:38:04 【问题描述】:

我有一组列表,我想从 无论每个列表中的元素顺序如何删除重复项,如下所示:

我有这个作为输入 [[-1,-1,2],[0,-1,1],[1,-1,0],[2,-1,-1],[-1,2,-1],[-1,1,0],[0,1,-1],[-1,0,1],[1,0,-1]]

当我使用 Set<Set> 来优化我的元素时,它完成了部分工作,但我得到了 [[1,-1,0],[-1,2]],这是合乎逻辑的,因为内部 Set 优化了 [-1,-1,2] 的重复项。

当我尝试使用 Set<List> 时,我无法优化我的元素,这让我得到了这个 [[-1,-1,2],[0,-1,1],[1,-1,0],[2,-1,-1],[-1,2,-1],[-1,1,0],[0,1,-1],[-1,0,1],[1,0,-1]]

那么我怎样才能设法优化重复项并保持生成的三元组完好无损?

提前谢谢你。

【问题讨论】:

【参考方案1】:

我认为您可以使用排序来按照您指定的方式使用 Set 和 List:

import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

class Main 
    
    public static void main(String[] args) 
        int[][] arrayWithDuplicates = new int[][]   -1, -1, 2 ,  0, -1, 1 ,  1, -1, 0 ,  2, -1, -1 ,
                 -1, 2, -1 ,  -1, 1, 0 ,  0, 1, -1 ,  -1, 0, 1 ,  1, 0, -1  ;
        System.out.printf("arrayWithDuplicates = %s%n", Arrays.deepToString(arrayWithDuplicates));
        int[][] arrayWithoutDuplicates = getArrayWithoutDuplicates(arrayWithDuplicates);
        System.out.printf("arrayWithoutDuplicates = %s%n", Arrays.deepToString(arrayWithoutDuplicates));
    

    public static int[][] getArrayWithoutDuplicates(int[][] array) 
        List<int[]> listWithoutDuplicates = new ArrayList<>();
        Set<List<Integer>> seenSubLists = new HashSet<>();
        for (int[] ints : array) 
            List<Integer> sortedInts = Arrays.stream(ints).boxed().sorted().collect(Collectors.toList());
            if (!seenSubLists.contains(sortedInts)) 
                listWithoutDuplicates.add(ints);
                seenSubLists.add(sortedInts);
            
        
        return listWithoutDuplicates.toArray(new int[listWithoutDuplicates.size()][]);
    


输出:

arrayWithDuplicates = [[-1, -1, 2], [0, -1, 1], [1, -1, 0], [2, -1, -1], [-1, 2, -1], [-1, 1, 0], [0, 1, -1], [-1, 0, 1], [1, 0, -1]]
arrayWithoutDuplicates = [[-1, -1, 2], [0, -1, 1]]

【讨论】:

【参考方案2】:
    final Set<List<Integer>> sortedLists = new HashSet<>();
    Set<List<Integer>> newLists = lists.stream()
            .map(integers -> 
                List<Integer> sorted = integers.stream().sorted().collect(Collectors.toList());
                if (sortedLists.contains(sorted)) 
                    return null;
                
                sortedLists.add(sorted);
                return integers;
            )
            .filter(Objects::nonNull)
            .collect(Collectors.toSet());

【讨论】:

【参考方案3】:

您可以创建一个类来表示您的集合元素并为它们提供您想要的行为。也就是说,如果两个元素包含相同的整数而不考虑顺序,则它们相等。

import java.util.Arrays;
public class IntList extends Object 
    // I will keep the original array but you can just sort it in place if that makes sense
    private int[] array; // The orignal array
    private int[] sortedArray; // Sorted copy of the original array
    public IntList( int[] array ) 
        this.array = array;
        this.sortedArray = array.clone();
        Arrays.sort( this.sortedArray );
    
    @Override
    public boolean equals( Object o ) 
        // This object is equal to another if they are:
        //   the same instance or instances of this class with equal sorted arrays
        boolean result;
        if ( o == this ) 
            result = true;
         else 
            if ( ! ( o instanceof IntList ) ) 
                result = false;
             else 
                IntList other = ( IntList ) o;
                result = Arrays.equals( this.sortedArray, other.sortedArray );
            
        
        return result;
    
    @Override
    public int hashCode() 
        // Used by HashSet
        return Arrays.hashCode( this.sortedArray );
    
    @Override
    public String toString() 
        return Arrays.toString( this.sortedArray );
    

然后你可以用这个类的元素构造一个Set:

import java.util.Arrays;
import java.util.Set;
import java.util.HashSet;

public class main 
    public static void main(String[] args) 
        int[][] input = new int[][]   -1, -1, 2 ,  0, -1, 1 ,  1, -1, 0 ,  2, -1, -1 ,
                 -1, 2, -1 ,  -1, 1, 0 ,  0, 1, -1 ,  -1, 0, 1 ,  1, 0, -1  ;

        System.out.printf("input = %s%n", Arrays.deepToString(input));

        Set<IntList> set = new HashSet<IntList>();
        for( int[] currIntArray: input ) 
            IntList list = new IntList( currIntArray );
            set.add( list );

        
        System.out.printf( "output = %s%n", set.toString());
    

结果

input = [[-1, -1, 2], [0, -1, 1], [1, -1, 0], [2, -1, -1], [-1, 2, -1], [-1, 1, 0], [0, 1, -1], [-1, 0, 1], [1, 0, -1]]
output = [[-1, -1, 2], [0, -1, 1]]

您执行此操作的方式实际上取决于您的问题域的更大背景。我认为您不太可能真的想要一个名为 IntList 的公共类,但您可能会将其包含在您自己的 Set 实现中,或模型中的其他位置。

【讨论】:

以上是关于如何从Java列表中删除重复项的主要内容,如果未能解决你的问题,请参考以下文章

如何从我的列表中删除重复项? [复制]

从列表中删除重复项?

如何从列表 Dart 中删除重复项 |扑

java 82.从排序列表II(递归).java中删除重复项

java 82.从排序列表II(递归).java中删除重复项

java 82.从排序列表II(递归).java中删除重复项