如何检测 ArrayList 和 return 具有重复元素的新列表中的重复项

How to detect duplicates in ArrayList and return new List with duplicated elements

示例:

您收到一个包含以下内容的 ArrayList:“A,B,A,B,C,A,F,Z,C,H”

新的输出列表应该只包含重复的元素:“A,B,C”

您可以使用 set 集合来识别重复项,因为集合是不同元素的未排序列表。如果 Set 的 add() 方法 returns false 表示元素已经存在于列表中。

public static void main(String args[]) {
        ArrayList<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("A");
        list.add("F");
        list.add("Z");
        list.add("C");
        list.add("H");

        Set<String> set = new HashSet<>();
        Set<String> duplicateElements = new HashSet<>();
        for (String element : list) {
            if (!set.add(element)) {
                duplicateElements.add(element);
            }
        }

        System.out.println("Duplicate Elements : " + duplicateElements);

    }

您可以使用频率散列映射来跟踪计数,并使用该映射过滤掉重复项

      List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("A");
        list.add("F");
        list.add("Z");
        list.add("C");
        list.add("H");
        Map<String, Integer> freqMap = new HashMap<>();
        for (String s: list) {
            if(freqMap.containsKey(s)){
                freqMap.put(s, freqMap.get(s)+1);
            } else {
                freqMap.put(s, 1);
            }
        }

        List<String> result = new ArrayList<>();
        for(Map.Entry<String, Integer> entry: freqMap.entrySet()){
            if(entry.getValue() > 1){
                result.add(entry.getKey());
            }
        }

tl;博士

Set.copyOf( list ).stream().filter( s -> list.indexOf( s ) != list.lastIndexOf( s ) ).sorted().toList()

或者,重新格式化:

Set
        .copyOf( 
            list     // List.of( "A,B,A,B,C,A,F,Z,C,H".split( "," ) )
        )
        .stream()
        .filter( 
            s -> list.indexOf( s ) != list.lastIndexOf( s ) 
        )
        .sorted()
        .toList()

[A, B, C]

详情

根据您输入的字符串创建一个列表。使用 String#split 生成零件数组。将该数组提供给 List.of 会生成一个不可修改的 List 对象。

List < String > list = List.of( "A,B,A,B,C,A,F,Z,C,H".split( "," ) );

接下来,我们需要一个不同的字母集合,消除重复项。 Set 根据定义没有重复项。将我们的 List 传递给 Set.copyOf 会产生一个不可修改的 Set 对象。

Set < String > distinct = Set.copyOf( list );

我们要检查不同集合中的每个值,看看是否在原始列表中不止一次。

我们知道每个元素至少出现在列表中一次。所以我们可以使用 List#indexOf 来获取列表中的索引(从零开始的位置)。而我们可以得到List#lastIndexOf来得到最后一个重复的位置。如果两次呼叫 return 相同的 号码,我们知道只有一次。如果两次调用return不同索引号,我们就知道我们有不止一个。因此,我们进行谓词测试,比较每个 String 元素的这两个调用:s -> list.indexOf( s ) != list.lastIndexOf( s ).

我们可以使用流而不是写循环。我们调用 Set#stream 来生成不同集合元素的流。

我们过滤流中找到的第一个和最后一个索引不同的元素,同时忽略那些未通过谓词测试的元素。对于那些通过谓词测试的,首先我们排序,然后收集到 List.

List < String > dups =
        distinct
                .stream()
                .filter( s -> list.indexOf( s ) != list.lastIndexOf( s ) )
                .sorted()
                .toList();  // Before Java 16, replace with `.collect( Collectors.toList() );`.

list = [A, B, A, B, C, A, F, Z, C, H]

distinct = [A, H, F, Z, C, B]

dups = [A, B, C]

function dup(array) {
  var tab = array[0].split(",");
  var obj = {};
  var result = [];
  for (var i = 0; i < tab.length; i++) {
    if (!obj[tab[i]]) {
      obj[tab[i]] = 1;
    } else {
      obj[tab[i]]++;
    }
  }
  for (var key in obj) {
    if (obj[key] > 1) {
      result.push(key);
    }
  }
  return result;
}

只是为了提供一个替代方案,您可以使用流实现相同的算法:

list.stream()
    .collect(Collectors.groupingBy(v -> v, Collectors.counting())
    .entrySet().stream().filter(e -> e.getValue() > 1)
    .map(e -> e.getKey())
    .toList();