随机ArrayIndexOutOfBoundsException,使用流按值对Map元素进行排序 [英] Random ArrayIndexOutOfBoundsException, using stream to order Map elements by value

查看:134
本文介绍了随机ArrayIndexOutOfBoundsException,使用流按值对Map元素进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近几天,我开始玩"一些Java 8功能,例如流(我研究了一些文档和几个示例).

in the last days I'm starting to "play" with some Java 8 features, like stream (I studied a bit of documentation and several examples).

在我的应用程序中,我有一个Map,我需要获取三个具有最高值的元素(浮点部分).

In my application I have a Map and I need to get the three element with highest value (the float part).

我尝试对代码进行不同的修改(以及其中一些解决方案:

I tried different modifications to my code (and some of these solutions also: Sort a Map<Key, Value> by values (Java) ), for example:

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));

但是reslt总是一样的:有时代码可以正常工作,其他代码却给了我

But the reslt is always the same: sometimes the code works fine, other it gives me a

java.lang.ArrayIndexOutOfBoundsException: 19

在极少数情况下,超出范围的索引为18.

In rare cases, the index out of the bounds is 18.

这种随机"行为(18、19或正确的细节)使我想到了并行线程"问题.

This "random" behaviour (18, 19, or correct elaborations) makes me think to a "parallel threading" problem.

我确定great地图始终包含20个元素...如果我打印它们,我会收到:

I'm sure that great map has always 20 elements... if I print them I receive:

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

我意识到有17个对象可以成为前3个对象...但这对我的算法来说不是问题.

I'm conscious that 17 objects are candidate to be the first 3... but it is not a problem for my algorithm.

您能以某种方式帮助我吗?

Can you help me in some way?

谢谢

方法createMapWith20Elements()有一个虚拟名称,可以更好地解释我的情况:我确定它返回20个元素,因为它可以读取数据库...但是它应该返回任何匹配的记录.

The method createMapWith20Elements() has a dummy name for better explaining my situation: I'm sure it returns 20 elements because it makes a DB reading... but it should return any matching record.

以结尾结尾

// myIds is an ArrayList<Long>
myIds.parallelStream().forEach(e -> trust.put(e, 0f));
return trust;

替换为myIds.stream()似乎工作正常...我无法弄清楚如何使用parallelStream写入对象(Collection而不是Stream),并返回对象本身(Collection),在调用函数中可能会导致这种问题.

Replacing with myIds.stream() it seems working fine... I'm not able to figure how using parallelStream to write to an object (Collection and not Stream), and returning the object itself (Collection), in the calling function it can lead to this kind of problem.

推荐答案

我认为问题出在方法createMapWith20Elements().

I think that the problem is the method createMapWith20Elements().

您正在同时在地图中插入元素(可能是HashMap或TreeMap),并且HashMap和TreeMap均未同步.因此,并发插入(放置方法调用)会破坏映射结构(您将获得损坏的映射).

You are inserting elements in the map (probably a HashMap or a TreeMap) concurrently and both HashMap and TreeMap are not synchronized. So concurrent insertions (put method invocations) break the map structure (you get a corrupted map).

正如您提到的:

// myIds is an ArrayList<Long>
myIds.parallelStream().forEach(e -> trust.put(e, 0f));
return trust;

有时会产生错误.但是

// myIds is an ArrayList<Long>
myIds.stream().forEach(e -> trust.put(e, 0f));
return trust;

不会产生错误.

如果要同时插入,则必须使用同步包装器.因此您的代码应为:

If you want to insert concurrently then you must use a synchronized wrapper. So your code should be:

// myIds is an ArrayList<Long>
Map<Long, Float> syncTrust = Collections.synchronizedSortedMap(trust);
myIds.parallelStream().forEach(e -> syncTrust.put(e, 0f));
return trust;

这篇关于随机ArrayIndexOutOfBoundsException,使用流按值对Map元素进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆