这是输入和输出的SQL版本:
with tab1 as (
select 1 as id from dual union all
select 1 as id from dual union all
select 2 as id from dual union all
select 2 as id from dual union all
select 5 as id from dual
)
select id from tab1 group by id having count(id)=1;
Output is Id=5 and count is 1
5不重复,如何使用JAVA 8流实现它?
我在下面尝试过,但是显然给出了错误的结果
List<Integer> myList = new ArrayList<Integer>();
myList.add(1);
myList.add(1);
myList.add(2);
myList.add(2);
myList.add(5);
Long f = myList.stream()
.distinct().count();
System.out.println(f);
答案 0 :(得分:4)
long result = myList.stream()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()))
.entrySet()
.stream()
.filter(entry -> entry.getValue() == 1)
.map(Entry::getKey)
.count();
好吧,您将所有元素收集到Map<Integer, Long>
中,其中的键是值本身,值是其重复的次数。稍后,我们从结果映射中流式传输条目集,然后filter
仅流传计数为1
的条目(这意味着它们不会重复),之后我们将map
到{{1} }-从列表中获取该值并计数。
答案 1 :(得分:2)
一种替代方法是从列表中过滤出重复的元素,但效率不高,因此仅在列表较小时才使用它:
List<Integer> result = myList.stream()
.filter(i -> Collections.frequency(myList, i) == 1)
.collect(toList());
答案 2 :(得分:2)
为完整起见,这是一种Java 8方式,它不使用流:
Map<Integer, Long> frequencyMap = new LinkedHashMap<>(); // preserves order
myList.forEach(element -> frequencyMap.merge(element, 1L, Long::sum)); // group, counting
frequencyMap.values().removeIf(count -> count > 1); // remove repeated elements
Set<Integer> nonRepeated = frequencyMap.keySet(); // this is your result
这使用Map.merge
用每个元素的计数填充地图。然后,对映射的值使用Collection.removeIf
,以删除其值大于1
的条目。
我发现这种方式比使用流更紧凑,更易读。
答案 3 :(得分:1)
您可以这样做
Map<Integer, Long> countByNumber = myList.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
List<Integer> uniqueNumbers = myList.stream()
.filter(n -> countByNumber.get(n) == 1)
.collect(Collectors.toList());
首先使用值和出现次数创建一个地图。然后遍历数字List
,从map
获取每个数字的出现次数。如果出现的次数为1,则将其收集到一个单独的容器中。
如果想一次完成,就在这里。
List<Integer> uniqueNumbers = myList.stream()
.collect(Collectors.collectingAndThen(Collectors.groupingBy(Function.identity(),
Collectors.counting()),
m -> myList.stream().filter(n -> m.get(n) == 1).collect(Collectors.toList())));
答案 4 :(得分:1)
可供您考虑的另一种选择:
//Create a map where the key is the element you want to count and the value is the actual count
Map<Integer, Long> countByItem = myList.stream()
.collect(Collectors.groupingBy(
Function.identity(), //the function that will return the key
Collectors.counting())); //the function that will actually count the occurences
//Once you have that map, all you need to do is filter for the registers with count == 1
List<Integer> result = countByItem.entrySet().stream()
.filter(entry -> entry.getValue() == 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());