Java 세트를 어떻게 반복하고 수정합니까?
정수 집합이 있고 집합의 모든 정수를 증가시키고 싶다고 가정 해 보겠습니다. 어떻게해야합니까?
반복하는 동안 세트에서 요소를 추가하고 제거 할 수 있습니까?
원래 세트를 반복하는 동안 요소를 "복사 및 수정"할 새 세트를 만들어야합니까?
편집 : 집합의 요소가 불변이면 어떻게됩니까?
Iterator 개체를 사용하여 반복하는 동안 집합에서 안전하게 제거 할 수 있습니다. 반복하는 동안 API를 통해 집합을 수정하려고하면 반복기가 중단됩니다. Set 클래스는 getIterator ()를 통해 반복자를 제공합니다.
그러나 Integer 객체는 변경할 수 없습니다. 내 전략은 세트를 반복하고 각 Integer i에 대해 새 임시 세트에 i + 1을 추가하는 것입니다. 반복이 완료되면 원본 세트에서 모든 요소를 제거하고 새 임시 세트의 모든 요소를 추가하십시오.
Set<Integer> s; //contains your Integers
...
Set<Integer> temp = new Set<Integer>();
for(Integer i : s)
temp.add(i+1);
s.clear();
s.addAll(temp);
반복기 객체를 사용하여 세트의 요소를 탐색하는 경우 원하는 작업을 수행 할 수 있습니다. 이동 중에도 제거 할 수 있습니다. 그러나 for 루프 (각 종류의 "표준")에서 제거하면 문제가 발생합니다.
Set<Integer> set = new TreeSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
//good way:
Iterator<Integer> iterator = set.iterator();
while(iterator.hasNext()) {
Integer setElement = iterator.next();
if(setElement==2) {
iterator.remove();
}
}
//bad way:
for(Integer setElement:set) {
if(setElement==2) {
//might work or might throw exception, Java calls it indefined behaviour:
set.remove(setElement);
}
}
@mrgloom의 의견에 따라 위에서 설명한 "나쁜"방식이 왜 나쁜지에 대한 자세한 내용은 다음과 같습니다.
Java가이를 구현하는 방법에 대해 너무 자세하게 설명하지 않고도 높은 수준에서 "나쁜"방법은 Java 문서에 명시되어 있으므로 나쁘다고 말할 수 있습니다.
https://docs.oracle.com/javase/8/docs/api/java/util/ConcurrentModificationException.html
무엇보다도 다음과 같이 규정하십시오 (내 강조) :
" 다른 스레드가 반복되는 동안 하나 개의 스레드가 컬렉션을 수정하는 예를 들어, 일반적으로 허용되지 않는다. 일반적으로, 반복 처리의 결과는 이러한 상황에서 정의되지 않은 있습니다. 모든 범용 수집을 포함한 일부 반복자 구현 ( JRE에서 제공하는 구현)은이 동작이 감지되면이 예외를 throw하도록 선택할 수 있습니다. "(...)
" 이 예외가 항상 다른 스레드에 의해 객체가 동시에 수정되었음을 나타내는 것은 아닙니다. 단일 스레드가 객체의 계약을 위반하는 일련의 메서드 호출을 실행하면 객체에서이 예외를 throw 할 수 있습니다. 예를 들어, 스레드는 실패-빠른 반복기를 사용하여 콜렉션을 반복하는 동안 콜렉션을 직접 수정합니다. 반복자는이 예외를 발생시킵니다. "
더 자세히 알아 보려면 forEach 루프에서 사용할 수있는 객체는 "java.lang.Iterable"인터페이스 ( 여기에서 javadoc ) 를 구현해야합니다 . 이는 요청시 인스턴스화되고 생성 된 Iterable 개체에 대한 참조를 내부적으로 포함 하는 Iterator (이 인터페이스에있는 "Iterator"메서드를 통해)를 생성합니다. 그러나 Iterable 객체가 forEach 루프에서 사용되는 경우이 반복기의 인스턴스는 사용자에게 숨겨집니다 (어떤 방식 으로든 직접 액세스 할 수 없음).
This, coupled with the fact that an Iterator is pretty stateful, i.e. in order to do its magic and have coherent responses for its "next" and "hasNext" methods it needs that the backing object is not changed by something else than the iterator itself while it's iterating, makes it so that it will throw an exception as soon as it detects that something changed in the backing object while it is iterating over it.
자바는 이것을 "fail-fast"반복이라고 부릅니다. 즉, 일반적으로 Iterable 인스턴스를 수정하는 액션이 있습니다 (반복자가 반복하는 동안). "fail-fast"개념의 "실패"부분은 이러한 "실패"동작이 발생하는시기를 감지하는 반복자의 기능을 나타냅니다. "fail-fast"의 "fast"부분 (내 의견으로는 "best-effort-fast"라고 부름) 은 "fail"작업이 다음 과 같은 것을 감지 할 수있는 즉시 ConcurrentModificationException 을 통해 반복을 종료합니다. 우연히 있다.
반복자의 의미가별로 마음에 들지 않습니다. 이것을 옵션으로 고려하십시오. 내부 상태를 적게 게시하면 더 안전합니다.
private Map<String, String> JSONtoMAP(String jsonString) {
JSONObject json = new JSONObject(jsonString);
Map<String, String> outMap = new HashMap<String, String>();
for (String curKey : (Set<String>) json.keySet()) {
outMap.put(curKey, json.getString(curKey));
}
return outMap;
}
You could create a mutable wrapper of the primitive int and create a Set of those:
class MutableInteger
{
private int value;
public int getValue()
{
return value;
}
public void setValue(int value)
{
this.value = value;
}
}
class Test
{
public static void main(String[] args)
{
Set<MutableInteger> mySet = new HashSet<MutableInteger>();
// populate the set
// ....
for (MutableInteger integer: mySet)
{
integer.setValue(integer.getValue() + 1);
}
}
}
Of course if you are using a HashSet you should implement the hash, equals method in your MutableInteger but that's outside the scope of this answer.
Firstly, I believe that trying to do several things at once is a bad practice in general and I suggest you think over what you are trying to achieve.
It serves as a good theoretical question though and from what I gather the CopyOnWriteArraySet
implementation of java.util.Set
interface satisfies your rather special requirements.
http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/CopyOnWriteArraySet.html
참고URL : https://stackoverflow.com/questions/7393398/how-do-i-iterate-and-modify-java-sets
'Program Tip' 카테고리의 다른 글
IIS에서 기본 웹 사이트 다시 만들기 (0) | 2020.10.14 |
---|---|
MySQL은 ORDER BY에서 행 위치를 얻습니다. (0) | 2020.10.14 |
배치 파일을 통해 cmd 명령을 어떻게 실행합니까? (0) | 2020.10.14 |
Homebrew 용 Github API 토큰 설정 (0) | 2020.10.14 |
LPCWSTR은 무엇을 의미하며 어떻게 처리해야합니까? (0) | 2020.10.14 |