最近,我在一次采訪中被問到這個問題:
如何在不使用 java Stream 的方法
List
的情況下找到重復元素?Integer
distinct()
這應該由 Java 的 Stream API 完成,但不應該使用distinct()
方法。
存根代碼:
List<Integer> listOfInt = new ArrayList<>();
uj5u.com熱心網友回復:
您可以使用頻率收集器來做到這一點。沒看過優化,但這不會使用 distinct
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import static java.util.stream.Collectors.toSet;
import java.util.Collections;
public class DetectDuplicates{
public static void main(String args[]) {
List<Integer> companyIds = new ArrayList<Integer>();
companyIds.add(1);
companyIds.add(1);
companyIds.add(2);
companyIds.add(3);
companyIds.add(3);
Set<Integer> duplicateCompanies = companyIds
.stream()
.filter(company -> Collections.frequency(companyIds, company) > 1)
.collect(toSet());
System.out.println("Duplicate companies " duplicateCompanies);
}
}
這將列印
Duplicate companies [1, 3]
uj5u.com熱心網友回復:
您也可以通過按計數分組并使用collectingAndThen
使其單次傳遞來做到這一點(而不是使用超過 1 個流)
List<Integer> numbers = List.of(1, 2, 2, 3, 3, 3, 4, 4, 4, 4);
Set<Integer> duplicates = numbers.stream()
.collect(Collectors.collectingAndThen(Collectors.groupingBy(Function.identity(), Collectors.counting()), frequencyMap -> {
frequencyMap.values().removeIf(k -> k < 2);
return frequencyMap.keySet();
}));
uj5u.com熱心網友回復:
如果可以使用第三方庫,則可以Bag
使用Eclipse Collections創建一個,并使用selectDuplicates
on 方法Bag
查找重復項。首先,您需要List
使用Bag
. list.stream().collect(Collectors2.toBag())
這將滿足使用 Java Streams API 的要求。
@Test
public void selectDuplicates()
{
List<Integer> list = new ArrayList<>(List.of(1, 2, 2, 3, 3, 3, 4, 4, 4, 4));
Set<Integer> duplicates = list.stream()
.collect(Collectors2.toBag()).selectDuplicates().toSet();
Set<Integer> expected = Set.of(2, 3, 4);
Assertions.assertEquals(expected, duplicates);
}
如果不能使用第三方庫,那么可以使用JDK中的groupingBy
and counting
Collectors
。
@Test
public void selectDuplicatesJDK()
{
List<Integer> list = new ArrayList<>(List.of(1, 2, 2, 3, 3, 3, 4, 4, 4, 4));
Map<Integer, Long> counts = list.stream()
.collect(Collectors.groupingBy(i -> i, Collectors.counting()));
counts.values().removeIf(count -> count < 2L);
Set<Integer> duplicates = counts.keySet();
Set<Integer> expected = Set.of(2, 3, 4);
Assertions.assertEquals(expected, duplicates);
}
注意:我是 Eclipse Collections 的提交者
uj5u.com熱心網友回復:
方法 distinct()
將不允許您“查找重復的元素”。distinct()
僅使用方法,您甚至永遠不會知道源中是否有任何重復項。顧名思義,它將為您提供獨特的元素,僅此而已。
從源串列中過濾掉重復元素的一種方法是生成一個中間值Map<Integer,Boolean>
,其中鍵是元素本身,值表示特定鍵在源串列中是否有重復項。
這可以通過使用內置收集器來完成toMap()
:
List<Integer> duplicates = sourceList.stream()
.collect(Collectors.toMap(
Function.identity(), // the key - an element itself
next -> false, // the value of `false` - the element isn't proved yet to be a duplicate because it has been encountered for the first time
(left, right) -> true // the value of `true` - the element is a duplicate
))
.entrySet().stream()
.filter(Map.Entry::getValue)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/490828.html