在最后几天,我开始"玩"一些Java 8功能,比如流(我研究了一些文档和几个例子).
在我的应用程序中,我有一个Map,我需要获得具有最高值的三个元素(float部分).
我尝试对我的代码进行不同的修改(以及其中一些解决方案:按地图<键,值>按值(Java)排序),例如:
Map<Long, Float> great = createMapWith20Elements();
Map<Long, Float> small = great.entrySet().stream()
.sorted(Map.Entry.<Long, Float>comparingByValue().reversed())
.limit(3)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Run Code Online (Sandbox Code Playgroud)
但是reslt总是一样的:有时代码工作正常,其他它给了我一个
java.lang.ArrayIndexOutOfBoundsException: 19
Run Code Online (Sandbox Code Playgroud)
在极少数情况下,超出界限的指数为18.
这种"随机"行为(18,19或正确的阐述)让我想到了一个"平行线程"问题.
我确定great地图总是有20个元素......如果我打印它们我收到:
2,-0.5
3,0.0
4,0.0
5,0.0
6,0.0
7,-0.33333334
8,0.0
9,0.0
10,0.0
11,0.0
12,0.5
13,0.0
14,0.0
15,-0.5
18,0.0
19,0.0
21,0.0
22,0.0
23,0.0
24,0.0
Run Code Online (Sandbox Code Playgroud)
我意识到有17个对象可以成为前3个......但对我的算法来说这不是问题.
你能以某种方式帮助我吗?
谢谢
编辑:
该方法createMapWith20Elements()有一个虚拟名称,以便更好地解释我的情况:我确定它返回20个元素,因为它使数据库读取...但它应该返回任何匹配的记录.
顺便说一下它结束了
// myIds is an ArrayList<Long>
myIds.parallelStream().forEach(e -> trust.put(e, 0f));
return trust;
Run Code Online (Sandbox Code Playgroud)
替换myIds.stream()它似乎工作正常...我无法弄清楚如何使用parallelStream写入对象(Collection而不是Stream),并返回对象本身(Collection),在调用函数中它可能导致这种问题.
小智 5
我认为问题是方法createMapWith20Elements().
您正在同时在地图中插入元素(可能是HashMap或TreeMap),并且HashMap和TreeMap都不会同步.因此并发插入(put方法调用)会破坏地图结构(导致地图损坏).
如你所说:
// myIds is an ArrayList<Long>
myIds.parallelStream().forEach(e -> trust.put(e, 0f));
return trust;
Run Code Online (Sandbox Code Playgroud)
有时会产生错误.但
// myIds is an ArrayList<Long>
myIds.stream().forEach(e -> trust.put(e, 0f));
return trust;
Run Code Online (Sandbox Code Playgroud)
不会产生错误.
如果要同时插入,则必须使用同步包装器.所以你的代码应该是:
// myIds is an ArrayList<Long>
Map<Long, Float> syncTrust = Collections.synchronizedSortedMap(trust);
myIds.parallelStream().forEach(e -> syncTrust.put(e, 0f));
return trust;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2903 次 |
| 最近记录: |