Collections.singleton(null)와 Collections.removeAll(Collections.singleton(null)) 예시
general java 2016. 3. 15. 23:47Collection에서 add나 remove를 할 때, loop 안에서 작업하면 CME 가 발생할 수 있다.
@Test
public void exceptionTest() {
List<Member> members = Lists.newArrayList();
members.add(new Member("1", "true"));
members.add(null);
members.add(new Member("3", "false"));
for (Member member : members) {
if (member == null) {
members.remove(member);
members.add(new Member("4", "true")); // 여기서 CME 발생
}
}
System.out.println(members.size());
}
결과
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at com.google.NullElementTest.exceptionTest(NullElementTest.java:20)
Collection에서 null 인 엘리먼트를 삭제하려면, Collections.removeAll()을 사용할 수 있다.
바로 Collections.removeAll(null)을 호출하면, cme가 발생한다.
따라서, 이를 해결하려면, Collection을 하나 만들고 null 엘리먼트를 추가한 후, members.removeAll(리스트)를 호출한다.
@Test
public void avoidNpeTest() {
List<Member> members = Lists.newArrayList();
members.add(new Member("1", "true"));
members.add(null);
members.add(new Member("3", "false"));
// members.removeAll(null); // error
List<Member> nullList = Lists.newArrayList();
nullList.add(null);
members.removeAll(nullList);
System.out.println(members);
}
결과
[com.google.NullElementTest$Member@2133c8f8[id=1,followable=true], com.google.NullElementTest$Member@3ac3fd8b[id=3,followable=false]]
조금 verbose하니, Collections.singleton(null)을 이용하면 이전 예시와 동일한 결과를 얻을 수 있다.
@Test
public void avoidElegantNpeTest() {
List<Member> members = Lists.newArrayList();
members.add(new Member("1", "true"));
members.add(null);
members.add(new Member("3", "false"));
System.out.println(Collections.singleton(null));
members.removeAll(Collections.singleton(null));
System.out.println(members);
}
결과
[null]
[com.google.NullElementTest$Member@2133c8f8[id=1,followable=true], com.google.NullElementTest$Member@3ac3fd8b[id=3,followable=false]]
참고 : 코드 전문
package com.google;
import com.clearspring.analytics.util.Lists;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import java.util.Collections;
import java.util.List;
public class CMETest {
@Test
public void exceptionTest() {
List<Member> members = Lists.newArrayList();
members.add(new Member("1", "true"));
members.add(null);
members.add(new Member("3", "false"));
for (Member member : members) {
if (member == null) {
members.remove(member);
members.add(new Member("4", "true"));
}
}
System.out.println(members.size());
}
@Test
public void avoidNpeTest() {
List<Member> members = Lists.newArrayList();
members.add(new Member("1", "true"));
members.add(null);
members.add(new Member("3", "false"));
// members.removeAll(null); // error
List<Member> nullList = Lists.newArrayList();
nullList.add(null);
members.removeAll(nullList);
System.out.println(members);
}
@Test
public void avoidElegantNpeTest() {
List<Member> members = Lists.newArrayList();
members.add(new Member("1", "true"));
members.add(null);
members.add(new Member("3", "false"));
System.out.println(Collections.singleton(null));
members.removeAll(Collections.singleton(null));
System.out.println(members);
}
class Member {
public String id;
public String followable;
public Member(String id, String f) {
this.id = id;
this.followable = f;
}
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
}
'general java' 카테고리의 다른 글
jenkins API 일부 (Jenkin api) - job 정보, job이 실행하는지 여부 (0) | 2016.03.17 |
---|---|
Apache common의 BooleanUtils.toBoolean()와 BooleanUtils.toBooleanDefaultIfNull() 예시 (0) | 2016.03.16 |
Guava의 Predicate과 Filter를 이용한 예시 (0) | 2016.03.15 |
Guava의 Joiner 예시 (0) | 2016.03.13 |
Guava의 Joiner 예시 (0) | 2016.03.13 |