我试图将我的数据库中所有具有相同名称的位置收集到一个列表中,以便为此我使用以下命令:
public static List<Location> searchRepe(List<Location>ls){
List<Location>res=new ArrayList<Location>();
for(Location l:ls){
ls.remove(l);
if(ls.stream().anyMatch(x>x.getProvinceName().equals(l.getProvinceName()))){
res.add(l);}
ls.add(l);
}
return res;
}
错误:线程"main"中的异常 java.util.ConcurrentModificationException
我首先删除列表的位置,然后检查是否有另一个具有相同名称的位置。检查位置名称是否在列表中后,我将其添加到我的 res 列表中。无论如何,我将始终保持原始列表不变,因为在检查后我将元素读取到列表中。我知道错误是由于我在每次迭代中都删除并添加,但是如果在每次迭代中我删除然后添加相同的元素,则列表的大小将始终相同。
有人可以告诉我更好的方法吗?如果可以使用java8
foreach
语句使用 Iterator
来检索 item,Iterator
不能直接删除 item,否则方法会抛出ConcurrentModificationException
。因此,您可以通过以下方法从列表中删除项目:
for (int index = 0; index < list.size(); index++) {
if(condition){
list.remove(index);
index--;
}
}
在您的问题中,您可以使用Multimap
这是库中的新集合类型Guava
如下所示:
public static List<Location> searchRepe(List<Location>ls){
Multimap<String,Location> locationMap = HashMultimap.create();
for (Location l : ls) {
locationMap.put(l.getProvinceName(),l);
}
List<Location> result=new ArrayList<>();
for (Map.Entry<String, Collection<Location>> entry : locationMap.asMap().entrySet()) {
Collection<Location> value = entry.getValue();
if(value.size()>1){
Location next = value.iterator().next();
result.add(next);
}
}
return result;
}
注意这条线locationMap.put(l.getProvinceName(),l)
,put
方法的结果取决于Location
类中的equals
方法。
如果你绝对想使用stream和java8,我相信这是正确的解决方案。只需过滤所有元素,其中出现次数基于ProvinceName
多个元素
public static List<Location> searchRepe(List<Location> ls) {
return ls.stream()
.filter(
location -> ls.stream()
.map(Location::getProvinceName)
.filter(n -> Objects.equals(n, location.getProvinceName()))
.count() > 1L
)
.collect(Collectors.toList());
}
或使用分组依据
public static List<Location> searchRepe(List<Location> ls) {
return ls.stream()
.collect(Collectors.groupingBy(Location::getProvinceName))
.entrySet()
.stream()
.map(Map.Entry::getValue)
.filter(entry -> entry.size() > 1)
.map(entry -> entry.get(1))
.collect(toList());
}