Java 使用流生成地图时忽略重复项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32312876/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ignore duplicates when producing map using streams
提问by Patan
Map<String, String> phoneBook = people.stream()
.collect(toMap(Person::getName,
Person::getAddress));
I get java.lang.IllegalStateException: Duplicate key
when a duplicated element is found.
java.lang.IllegalStateException: Duplicate key
当发现重复的元素时,我得到。
Is it possible to ignore such exception on adding values to the map?
是否可以在向地图添加值时忽略此类异常?
When there is duplicate it simply should continue by ignoring that duplicate key.
当有重复时,它应该继续忽略该重复键。
采纳答案by Tunaki
This is possible using the mergeFunction
parameter of Collectors.toMap(keyMapper, valueMapper, mergeFunction)
:
这可以使用以下mergeFunction
参数Collectors.toMap(keyMapper, valueMapper, mergeFunction)
:
Map<String, String> phoneBook =
people.stream()
.collect(Collectors.toMap(
Person::getName,
Person::getAddress,
(address1, address2) -> {
System.out.println("duplicate key found!");
return address1;
}
));
mergeFunction
is a function that operates on two values associated with the same key. adress1
corresponds to the first address that was encountered when collecting elements and adress2
corresponds to the second address encountered: this lambda just tells to keep the first address and ignores the second.
mergeFunction
是对与同一键关联的两个值进行操作的函数。adress1
对应于收集元素时遇到的第一个地址,adress2
对应于遇到的第二个地址:这个 lambda 只是告诉保留第一个地址并忽略第二个地址。
回答by alaster
As said in JavaDocs:
正如JavaDocs 中所说:
If the mapped keys contains duplicates (according to
Object.equals(Object)
), anIllegalStateException
is thrown when the collection operation is performed. If the mapped keys may have duplicates, usetoMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)
instead.
如果映射的键包含重复项(根据
Object.equals(Object)
),IllegalStateException
则在执行收集操作时会抛出an 。如果映射的键可能有重复项,请toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)
改用。
So you should use toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)
instead. Just provide a merge function, that will determine which one of duplicates is put in the map.
所以你应该toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)
改用。只需提供一个合并功能,它将确定将哪个重复项放入地图中。
For example, if you don't care which one, just call
例如,如果您不在乎是哪一个,只需致电
Map<String, String> phoneBook =
people.stream()
.collect(Collectors.toMap(Person::getName,
Person::getAddress,
(a1, a2) -> a1));
回答by Dherik
The @alaster answer help me a lot, but I would like to add a meaninful information if someone is trying to group the information.
@alaster 的回答对我有很大帮助,但如果有人试图对信息进行分组,我想添加一个有意义的信息。
If you have, per example, two Orders
with the same code
but different quantity
of products for each one, and your desire is sumthe quantities, you can do:
例如,如果您有两个Orders
相同code
但不同quantity
的产品,并且您希望将数量相加,则可以执行以下操作:
List<Order> listQuantidade = new ArrayList<>();
listOrders.add(new Order("COD_1", 1L));
listOrders.add(new Order("COD_1", 5L));
listOrders.add(new Order("COD_1", 3L));
listOrders.add(new Order("COD_2", 3L));
listOrders.add(new Order("COD_3", 4L));
listOrders.collect(Collectors.toMap(Order::getCode,
o -> o.getQuantity(),
(o1, o2) -> o1 + o2));
Result:
结果:
{COD_3=4, COD_2=3, COD_1=9}
回答by vaquar khan
Assuming you have people is List of object
假设你有人是对象列表
Map<String, String> phoneBook=people.stream()
.collect(toMap(Person::getName, Person::getAddress));
Now you need two steps :
现在你需要两个步骤:
1)
1)
people =removeDuplicate(people);
2)
2)
Map<String, String> phoneBook=people.stream()
.collect(toMap(Person::getName, Person::getAddress));
Here is method to remove duplicate
这是删除重复项的方法
public static List removeDuplicate(Collection<Person> list) {
if(list ==null || list.isEmpty()){
return null;
}
Object removedDuplicateList =
list.stream()
.distinct()
.collect(Collectors.toList());
return (List) removedDuplicateList;
}
Adding full example here
在此处添加完整示例
package com.example.khan.vaquar;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class RemovedDuplicate {
public static void main(String[] args) {
Person vaquar = new Person(1, "Vaquar", "Khan");
Person zidan = new Person(2, "Zidan", "Khan");
Person zerina = new Person(3, "Zerina", "Khan");
// Add some random persons
Collection<Person> duplicateList = Arrays.asList(vaquar, zidan, zerina, vaquar, zidan, vaquar);
//
System.out.println("Before removed duplicate list" + duplicateList);
//
Collection<Person> nonDuplicateList = removeDuplicate(duplicateList);
//
System.out.println("");
System.out.println("After removed duplicate list" + nonDuplicateList);
;
// 1) solution Working code
Map<Object, Object> k = nonDuplicateList.stream().distinct()
.collect(Collectors.toMap(s1 -> s1.getId(), s1 -> s1));
System.out.println("");
System.out.println("Result 1 using method_______________________________________________");
System.out.println("k" + k);
System.out.println("_____________________________________________________________________");
// 2) solution using inline distinct()
Map<Object, Object> k1 = duplicateList.stream().distinct()
.collect(Collectors.toMap(s1 -> s1.getId(), s1 -> s1));
System.out.println("");
System.out.println("Result 2 using inline_______________________________________________");
System.out.println("k1" + k1);
System.out.println("_____________________________________________________________________");
//breacking code
System.out.println("");
System.out.println("Throwing exception _______________________________________________");
Map<Object, Object> k2 = duplicateList.stream()
.collect(Collectors.toMap(s1 -> s1.getId(), s1 -> s1));
System.out.println("");
System.out.println("k2" + k2);
System.out.println("_____________________________________________________________________");
}
public static List removeDuplicate(Collection<Person> list) {
if (list == null || list.isEmpty()) {
return null;
}
Object removedDuplicateList = list.stream().distinct().collect(Collectors.toList());
return (List) removedDuplicateList;
}
}
// Model class
class Person {
public Person(Integer id, String fname, String lname) {
super();
this.id = id;
this.fname = fname;
this.lname = lname;
}
private Integer id;
private String fname;
private String lname;
// Getters and Setters
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
@Override
public String toString() {
return "Person [id=" + id + ", fname=" + fname + ", lname=" + lname + "]";
}
}
Results :
结果 :
Before removed duplicate list[Person [id=1, fname=Vaquar, lname=Khan], Person [id=2, fname=Zidan, lname=Khan], Person [id=3, fname=Zerina, lname=Khan], Person [id=1, fname=Vaquar, lname=Khan], Person [id=2, fname=Zidan, lname=Khan], Person [id=1, fname=Vaquar, lname=Khan]]
After removed duplicate list[Person [id=1, fname=Vaquar, lname=Khan], Person [id=2, fname=Zidan, lname=Khan], Person [id=3, fname=Zerina, lname=Khan]]
Result 1 using method_______________________________________________
k{1=Person [id=1, fname=Vaquar, lname=Khan], 2=Person [id=2, fname=Zidan, lname=Khan], 3=Person [id=3, fname=Zerina, lname=Khan]}
_____________________________________________________________________
Result 2 using inline_______________________________________________
k1{1=Person [id=1, fname=Vaquar, lname=Khan], 2=Person [id=2, fname=Zidan, lname=Khan], 3=Person [id=3, fname=Zerina, lname=Khan]}
_____________________________________________________________________
Throwing exception _______________________________________________
Exception in thread "main" java.lang.IllegalStateException: Duplicate key Person [id=1, fname=Vaquar, lname=Khan]
at java.util.stream.Collectors.lambda$throwingMergerSet<String> uniqueNames = new HashSet<>();
Map<String, String> phoneBook = people
.stream()
.filter(person -> person != null && !uniqueNames.add(person.getName()))
.collect(toMap(Person::getName, Person::getAddress));
(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1253)
at java.util.stream.Collectors.lambda$toMap(Collectors.java:1320)
at java.util.stream.ReduceOpsReducingSink.accept(ReduceOps.java:169)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.example.khan.vaquar.RemovedDuplicate.main(RemovedDuplicate.java:48)
回答by Shessuky
I have encountered such a problem when grouping object, i always resolved them by a simple way: perform a custom filter using a java.util.Set to remove duplicate object with whatever attribute of your choice as bellow
我在对对象进行分组时遇到过这样的问题,我总是通过一种简单的方法来解决它们:使用 java.util.Set 执行自定义过滤器以删除具有您选择的任何属性的重复对象,如下所示
Map<Integer, Data> dataMap = dataList.stream().collect(Collectors.toMap(Data::getId, data-> data, (data1, data2)-> {LOG.info("Duplicate Group For :" + data2.getId());return data1;}));
Hope this helps anyone having the same problem !
希望这可以帮助任何有同样问题的人!
回答by fjkjava
For grouping by Objects
按对象分组
final Map<String, String> doop = new HashMap<>();
doop.put("a", "1");
doop.put("b", "2");
final Map<String, String> lookup = new HashMap<>();
doop.put("c", "e");
doop.put("d", "f");
doop.entrySet().stream().collect(Collectors.toMap(e -> lookup.get(e.getKey()), e -> e.getValue()));
回答by Andrew
For anyone else getting this issue but without duplicate keys in the map being streamed, make sure your keyMapper function isn't returning null values.
对于遇到此问题但在流式传输的地图中没有重复键的任何其他人,请确保您的 keyMapper 函数没有返回 null values。
It's very annoying to track this down because the error will say "Duplicate key 1" when 1 is actually the valueof the entry instead of the key.
跟踪这个很烦人,因为当 1 实际上是条目的值而不是键时,错误会说“重复键 1” 。
In my case, my keyMapper function tried to look up values in a different map, but due to a typo in the strings was returning null values.
就我而言,我的 keyMapper 函数试图在不同的映射中查找值,但由于字符串中的拼写错误,返回空值。
##代码##