方法一:
这样就足够了:
for(String s : var )
if(Collections.frequency(var, s) > 1)
duplicates.add(s);
还有流:
var.stream().filter(s -> frequency(var, s) > 1).collect(toList());
一个运行的例子:
public static void main(String[] args) {
List<String> var = Arrays.asList("a", "b", "b", "c");
List<String> dup = var.stream().filter(s -> Collections.frequency(var, s) > 1).collect(Collectors.toList());
System.out.println(dup);
}
输出:
[b, b]
思路如下,考虑一下列表,检查每个元素在列表中出现的频率,如果它们出现不止一次,则添加到重复列表中。
方法2:
一个不太干净但时间复杂度更高的解决方案是使用该字符串的 per 频率的 Map,然后基于该 Map 构建重复列表:
List<String> dup = new ArrayList<>();
Map<String, Long> frequencies =
var.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
for (Map.Entry<String, Long> entry : frequencies.entrySet()){
for(int i = 0; i < entry.getValue() && entry.getValue() > 1; i++)
dup.add(entry.getKey());
}
方法 3:
具有线性时间复杂度O(N):
Set<String> set = new HashSet <>();
List<String> duplicates = new ArrayList<>();
Set<String> is_duplicated = new HashSet <>();
var.forEach(s -> {
if(set.contains(s)) {
is_duplicated.add(s);
duplicates.add(s);
}
else
set.add(s);
});
duplicates.addAll(is_duplicated);
System.out.println(duplicates);
可以利用Set.add 方法语义,即:
If this set already contains the element, the call leaves the set
unchanged and returns {@code false}.
将上面的代码缩短为:
Set<String> set = new HashSet <>();
List<String> duplicates = new ArrayList<>();
Set<String> to_add = new HashSet<>();
var.forEach(s -> {
if(!set.add(s)) {
to_add.add(s);
duplicates.add(s);
}
});
duplicates.addAll(to_add);
System.out.println(duplicates);