Weekly Learned - list에서 object 지우는 방법

문득 list에서 조건에 맞는 오브젝트를 지우는 방법에 대해 답변을 달던 중 과연 몇가지가 있을까 생각해봤습니다.

더 있을수도 있지만 세가지가 바로 생각이 났는데 이 방법에 대해 테스트 해볼려고 합니다.

방식은 개인적으로 많이 쓰는 getter/setter 방식의 vo에서 메소드를 이용해 지우도록 테스트 해봤습니다.

먼저 5000000개의 vo 리스트를 준비해봤습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class testVO {
private int id;
private String name;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

간단한 테스트에 lombok은 설정부터 귀찮아서 그냥 generate 메뉴를 이용해 작업을 합니다.

그리고 테스트 데이터를 준비합니다.

1
2
3
4
5
6
7
8
for (int i = 1; i <= 5000; i++) {
for (int j = 1; j <= 1000; j++) {
testVO vo = new testVO();
vo.setId(j);
vo.setName(j + "abcd");
list.add(vo);
}
}

1~1000까지의 데이터를 5000번 반복해서 입력합니다. 예를 들면 id가 1이고 name이 “1abcd”인 vo가 1000개있겠죠.

실제환경에서는 하나도 없을수도, 한개만 있을수도, 여러개가 있을수도 있지만 통제를 했습니다.

list.remove(i)

list를 for문으로 돌면서 가져오는 코드는 다음과 같죠.

1
2
3
4
5
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getName().equals("500abcd")) {
list.remove(i);
}
}

리스트를 돌면서 500abcd와 같은 값을 가져와서 지웁니다.

위 아래는 System.currentTimeMillis()메소드를 찍어서 구분을 했으며 실행 결과는 다음과 같이 나옵니다.

list.remove(i)

결과는 5694ms로 나오네요.

list.remove(object o)

이번엔 foreach문을 돌면서 지워보겠습니다.

코드는 다음과 같습니다.

1
2
3
4
5
6
7
8
Iterator<testVO> iter = list.iterator();

while (iter.hasNext()) {
testVO vo = iter.next();
if (vo.getName().equals("500abcd")) {
list.remove(vo);
}
}

foreach로 수정하려고 했으나 Iterator를 이용하기로 했습니다.

list를 직접 수정하면 오류가 나기에 list2를 따로 만들어서 Iterator이용은 list1 지우는 것은 list2를 지웁니다.

list.remove(obj)

결과는 11735ms가 나오네요.

list.removeif(java.util.function.Predicate)

java8의 자랑 람다식을 활용한 removeif 예제입니다.

해당 조건에 맞는 오브젝트를 전부 지웁니다.

1
list.removeIf(vo -> vo.getName().equals("500abcd"));

앞의 식에 비해 확줄어든 코드가 느껴지시나요?

돌려보겠습니다.

list.removeif()

결과는 103ms네요. 믿기지 않아서 3번돌려봤습니다.

내부 최적화가 엄청난것같네요.

결과

오늘부터 lambda쓰러갑니다..