从 Java 中的多个列表中获取所有重复值
Get all duplicate values from multiple list in Java
我想从多个整数列表中获取所有重复的值。
令人困惑的部分是这些整数列表位于像这样的 Map of Map 中 LinkedHashMap> streams
// sample value
{
break_desc100=
{
bDesc_1000=[62, 72, 82, 92, 102, 112, 122],
bDesc 1001=[180, 190, 200, 210, 220, 230, 240],
cMessage_1000=[112],
cMessage_1001=[232]
}
}
// for this one I want to get 112
到目前为止,我尝试使用 retainAll,但如果重复项列表彼此不相邻,我的代码将无法正常工作。
for (Map.Entry<String,LinkedHashMap<String,List<Integer>>> entry : streams.entrySet()) {
String currentStream = entry.getKey();
LinkedHashMap<String,List<Integer>> bDescList = entry.getValue();
for (Map.Entry<String,List<Integer>> bDesc : bDescList.entrySet()) {
if (firstIteration) {
prevBDesc = bDesc;
firstIteration = false;
} else {
List<Integer> currentList = prevBDesc.getValue();
List<Integer> nextList = bDesc.getValue();
duplicates = new ArrayList<Integer>(currentList);
duplicates.retainAll(nextList);
allDuplicates.addAll(duplicates); //Set<Integer>
prevBDesc = bDesc;
}
}
}
编辑:
对不起伙计们,我忘了补充说 运行 在 Java 1.5.
编辑
这假定您要查找任何重复值。这包括在同一列表中查找重复项。如果我误解了这个问题,请纠正我。
您可以在 O(N) 时间和 O(N) space 内完成此操作,方法是遍历嵌套散列,同时计算每个整数的出现次数。然后我们可以过滤出不止一次出现的整数。
Map<String, List<Integer>> innerMap = new HashMap<>();
innerMap.put("bDesc_1000", Arrays.asList(62, 72, 82, 92, 102, 112, 122));
innerMap.put("bDesc_1001", Arrays.asList(180, 190, 200, 210, 220, 230, 240));
innerMap.put("cMessage_1000", Collections.singletonList(112));
innerMap.put("cMessage_1001", Collections.singletonList(232));
Map<String, Map<String, List<Integer>>> map = new HashMap<>();
map.put("break_desc100", innerMap);
Map<Integer, Integer> occurrenceMap = new HashMap<>();
map.forEach((outerKey, outerValue) -> {
outerValue.forEach((innerKey, innerValue) -> {
innerValue.forEach((element -> occurrenceMap.merge(element, 1, Integer::sum)
));
});
});
List<Integer> duplicates = occurrenceMap.entrySet().stream()
.filter(e -> e.getValue() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(duplicates);
输出
[112]
这似乎是适合流的任务:
Map<Integer, Long> counts = streams.values().stream()
.flatMap(bDescList -> bDescList.values().stream())
.flatMap(nextList -> nextList.stream())
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()));
counts.values().removeIf(c -> c == 1L);
Set<Integer> duplicates = counts.keySet();
此代码首先创建一个计数图。为此,它首先流式传输外部映射的值,然后使用 Stream.flatMap
创建一个包含所有内部映射值的新流。由于这些值实际上是列表,我们需要再次使用 Stream.flatMap
,最终得到一个 Integer
的流。 (我保留了你问题中的变量名)。
我们收集到一个计数映射,其中键是来自所有内部映射列表值的数字,值是所有映射和列表中每个数字的计数。
然后,我们从计数图中删除所有值为 1
的条目。剩下的键是重复的数字。
编辑: 这是 Java 5 中的等效代码...
Map<Integer, Long> counts = new HashMap<Integer, Long>();
for (Map<String, List<Integer>> bDescList : streams.values()) {
for (List<Integer> bDesc : bDescList.values()) {
for (Integer n : bDesc) {
Long c = counts.get(n);
if (c == null) {
c = 0L;
}
counts.put(n, c + 1);
}
}
}
Iterator<Long> it = counts.values().iterator();
while (it.hasNext()) {
Long c = it.next();
if (c == 1L) {
it.remove();
}
}
Set<Integer> duplicates = counts.keySet();
这里的推理是完全一样的...我们通过迭代列表映射的映射来创建计数映射,然后我们删除计数为 1 的条目,剩下的键是重复项。
我想从多个整数列表中获取所有重复的值。
令人困惑的部分是这些整数列表位于像这样的 Map of Map 中 LinkedHashMap
// sample value
{
break_desc100=
{
bDesc_1000=[62, 72, 82, 92, 102, 112, 122],
bDesc 1001=[180, 190, 200, 210, 220, 230, 240],
cMessage_1000=[112],
cMessage_1001=[232]
}
}
// for this one I want to get 112
到目前为止,我尝试使用 retainAll,但如果重复项列表彼此不相邻,我的代码将无法正常工作。
for (Map.Entry<String,LinkedHashMap<String,List<Integer>>> entry : streams.entrySet()) {
String currentStream = entry.getKey();
LinkedHashMap<String,List<Integer>> bDescList = entry.getValue();
for (Map.Entry<String,List<Integer>> bDesc : bDescList.entrySet()) {
if (firstIteration) {
prevBDesc = bDesc;
firstIteration = false;
} else {
List<Integer> currentList = prevBDesc.getValue();
List<Integer> nextList = bDesc.getValue();
duplicates = new ArrayList<Integer>(currentList);
duplicates.retainAll(nextList);
allDuplicates.addAll(duplicates); //Set<Integer>
prevBDesc = bDesc;
}
}
}
编辑: 对不起伙计们,我忘了补充说 运行 在 Java 1.5.
编辑
这假定您要查找任何重复值。这包括在同一列表中查找重复项。如果我误解了这个问题,请纠正我。
您可以在 O(N) 时间和 O(N) space 内完成此操作,方法是遍历嵌套散列,同时计算每个整数的出现次数。然后我们可以过滤出不止一次出现的整数。
Map<String, List<Integer>> innerMap = new HashMap<>();
innerMap.put("bDesc_1000", Arrays.asList(62, 72, 82, 92, 102, 112, 122));
innerMap.put("bDesc_1001", Arrays.asList(180, 190, 200, 210, 220, 230, 240));
innerMap.put("cMessage_1000", Collections.singletonList(112));
innerMap.put("cMessage_1001", Collections.singletonList(232));
Map<String, Map<String, List<Integer>>> map = new HashMap<>();
map.put("break_desc100", innerMap);
Map<Integer, Integer> occurrenceMap = new HashMap<>();
map.forEach((outerKey, outerValue) -> {
outerValue.forEach((innerKey, innerValue) -> {
innerValue.forEach((element -> occurrenceMap.merge(element, 1, Integer::sum)
));
});
});
List<Integer> duplicates = occurrenceMap.entrySet().stream()
.filter(e -> e.getValue() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(duplicates);
输出
[112]
这似乎是适合流的任务:
Map<Integer, Long> counts = streams.values().stream()
.flatMap(bDescList -> bDescList.values().stream())
.flatMap(nextList -> nextList.stream())
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()));
counts.values().removeIf(c -> c == 1L);
Set<Integer> duplicates = counts.keySet();
此代码首先创建一个计数图。为此,它首先流式传输外部映射的值,然后使用 Stream.flatMap
创建一个包含所有内部映射值的新流。由于这些值实际上是列表,我们需要再次使用 Stream.flatMap
,最终得到一个 Integer
的流。 (我保留了你问题中的变量名)。
我们收集到一个计数映射,其中键是来自所有内部映射列表值的数字,值是所有映射和列表中每个数字的计数。
然后,我们从计数图中删除所有值为 1
的条目。剩下的键是重复的数字。
编辑: 这是 Java 5 中的等效代码...
Map<Integer, Long> counts = new HashMap<Integer, Long>();
for (Map<String, List<Integer>> bDescList : streams.values()) {
for (List<Integer> bDesc : bDescList.values()) {
for (Integer n : bDesc) {
Long c = counts.get(n);
if (c == null) {
c = 0L;
}
counts.put(n, c + 1);
}
}
}
Iterator<Long> it = counts.values().iterator();
while (it.hasNext()) {
Long c = it.next();
if (c == 1L) {
it.remove();
}
}
Set<Integer> duplicates = counts.keySet();
这里的推理是完全一样的...我们通过迭代列表映射的映射来创建计数映射,然后我们删除计数为 1 的条目,剩下的键是重复项。