I have seen many questions close to this one on this site, but not this exact one, so I will ask anyway. Apologies if this is a duplicate.
我在这个网站上看到了很多关于这个的问题,但不是这个问题,所以无论如何我都会问。如果这是重复的道歉。
I have a HashSet containing Points, which are displayed in a window. Since the Points are moving all the time, I need to always iterate over my HashSet in order to update the window. All in all, my main loop looks something like this:
我有一个包含Points的HashSet,它们显示在一个窗口中。由于Points一直在移动,我需要总是迭代我的HashSet以更新窗口。总而言之,我的主循环看起来像这样:
HashSet<Point> h = ...
while(true){
for(Point p : h){
p.update();
draw(p);
}
}
Now here is where things go south. I would like that, when the user clicks somewhere on the screen, a Point is added at this place. However, naive approach to add an element to the HashSet directly in the event handler fails, because you cannot modify it while it is being iterated. Base code of the naive approach:
现在这里是事情向南的地方。我想,当用户点击屏幕上的某个位置时,会在此处添加一个Point。但是,在事件处理程序中直接向HashSet添加元素的天真方法会失败,因为在迭代时无法对其进行修改。天真方法的基本代码:
public void mouseClicked(MouseEvent e){
h.add(new Point(e.getX, e.getY));
}
An idea I had in order to avoid that behaviour was to maintain a temporary List in which the points to add would be kept, waiting for the main iteration over the HashSet to finish in order to add the new points. But that doesn't really seem safe to me, since an (unlucky) user could manage to add a point while the List is being iterated.
我为了避免这种行为而想到的一个想法是维护一个临时List,其中要保留要添加的点,等待HashSet的主迭代完成以添加新点。但这对我来说似乎并不安全,因为(不幸)用户可以设法在迭代List时添加一个点。
So what is the Best Practice solution here?
那么这里的最佳实践解决方案是什么?
2 个解决方案
#1
1
This is Swing and Swing is single threaded, so this is not a problem. Simply
这是Swing和Swing是单线程的,所以这不是问题。只是
- get rid of the
while (true)
loop, - And don't try to iterate repeatedly and instantaneously as that leads to disaster.
- use a Swing Timer instead with a reasonable delay between iterations
- Now threading won't be an issue since you cannot be adding a Point to the list while it is being iterated through.
摆脱while(true)循环,
并且不要试图反复和瞬间迭代,因为这会导致灾难。
使用Swing Timer代替迭代之间的合理延迟
现在线程不会成为一个问题,因为在迭代过程中你不能将一个Point添加到列表中。
#2
0
I would probably have two identical HashSets, and add the value to the one you are not currently iterating over. Alternate between which one you iterate by simply having a boolean value.
我可能会有两个相同的HashSet,并将值添加到您当前没有迭代的那个。通过简单地使用布尔值来迭代哪一个迭代。
Some pseudo-code would be:
一些伪代码将是:
HashSet h1 = [...]
HashSet h2 = [...]
boolean b = true;
[...]
if(b) {
iterateOver(h1);
h1 = h2;
b = !b;
} else {
iterateOver(h2);
h2 = h1;
b = !b;
}
[...]
if(b) {
h2.add();
} else {
h1.add();
}
[...]
#1
1
This is Swing and Swing is single threaded, so this is not a problem. Simply
这是Swing和Swing是单线程的,所以这不是问题。只是
- get rid of the
while (true)
loop, - And don't try to iterate repeatedly and instantaneously as that leads to disaster.
- use a Swing Timer instead with a reasonable delay between iterations
- Now threading won't be an issue since you cannot be adding a Point to the list while it is being iterated through.
摆脱while(true)循环,
并且不要试图反复和瞬间迭代,因为这会导致灾难。
使用Swing Timer代替迭代之间的合理延迟
现在线程不会成为一个问题,因为在迭代过程中你不能将一个Point添加到列表中。
#2
0
I would probably have two identical HashSets, and add the value to the one you are not currently iterating over. Alternate between which one you iterate by simply having a boolean value.
我可能会有两个相同的HashSet,并将值添加到您当前没有迭代的那个。通过简单地使用布尔值来迭代哪一个迭代。
Some pseudo-code would be:
一些伪代码将是:
HashSet h1 = [...]
HashSet h2 = [...]
boolean b = true;
[...]
if(b) {
iterateOver(h1);
h1 = h2;
b = !b;
} else {
iterateOver(h2);
h2 = h1;
b = !b;
}
[...]
if(b) {
h2.add();
} else {
h1.add();
}
[...]