Collection이란?
Set 인터페이스
List 인터페이스
Map 인터페이스
유용한 컬렉션 메서드
Collections.sort()와 자바에서의 Comparator 사용
컬랙션 동기화
[참고]https://gangnam-americano.tistory.com/41
package me.whiteship.livestudy.Collections;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class App {
public static void main(String[] args) {
//List 생성
List<String> list = Arrays.asList("Lars","Simon");
//List를 이렇게도 생성할수있다.
// List는 인터페이스이므로 참조변수는 List 구현체를 가리켜야한다.
List<String> list1 = new ArrayList<>();
list1.add("LULU");
list1.add("LALA");
// 람다식을 이용하여 각 요소를 출력
list.forEach(i-> System.out.println(i));
list1.forEach(i-> System.out.println(i));
// or
list.forEach(System.out::println);
list1.forEach(System.out::println);
}
}
package me.whiteship.livestudy.Collections;
import me.whiteship.livestudy.review6.Student;
import java.util.ArrayList;
import java.util.Arrays;
public class ArrayListExample {
public static void main(String[] args) {
ArrayList list= new ArrayList(); // 타입 미설정 object로 선언된다.
ArrayList<Student> list1 = new ArrayList<Student>(); // 타입설정 Student객체만
ArrayList<Integer> list2 = new ArrayList<Integer>(); // 타입설정 int타입만 사용가능
ArrayList<Integer> list3 = new ArrayList<>(); // new에서 타입파라미터 생략가능.
ArrayList<Integer> list4 = new ArrayList<Integer>(10); // 초기용량 지정
ArrayList<Integer> list5 = new ArrayList<Integer>(Arrays.asList(1,2,3)); // 생성값 추가
}
}
package me.whiteship.livestudy.Collections;
import java.util.ArrayList;
import java.util.Arrays;
public class ArrayListExample {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(3); // 값 추가
list.add(null); // null값도 add 가능
list.add(1,10); // index 1 위치에 10 insert
}
}
ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(1,2,3));
arrayList.remove(1); // index 1 제거
arrayList.clear(); // 모든 값 제거
ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(1,2,3));
System.out.println(arrayList.size()); // 3 출력
package me.whiteship.livestudy.Collections;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
public class ArrayListExample {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(1,2,3));
System.out.println(arrayList.get(0)); // 0번째 인덱스 출력
for (Integer integer : arrayList) { // for문을 통한 전체 출력
System.out.println(integer);
}
Iterator iterator = arrayList.iterator(); // Iterator 선언
while(iterator.hasNext()){ // 다음값이 있는지 체크
System.out.println(iterator.next()); // 값 출력
}
}
}
output
1
1
2
3
1
2
3
package me.whiteship.livestudy.Collections;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
public class ArrayListExample {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(1,2,3,1));
System.out.println(arrayList.contains(1)); // list에 1이 있는지 검색: true
System.out.println(arrayList.indexOf(1)); // 1이 있는 index 반환 없으면 -1
}
}
output
true
0
package me.whiteship.livestudy.Collections;
import java.util.Arrays;
import java.util.LinkedList;
public class LinkedListExample {
public static void main(String[] args) {
LinkedList list = new LinkedList(); // 타입 미설정 Object로 선언된다.
LinkedList<Integer> list1= new LinkedList<Integer>(); // 타입설정 int타입만 사용가능하다
LinkedList<Integer> list2 = new LinkedList<>(); // new에서 타입 파라미터 생략가능
LinkedList<Integer> list3 = new LinkedList<Integer>(Arrays.asList(1,2,3)); // 생성시 값추가
}
}
package me.whiteship.livestudy.Collections;
import java.util.Arrays;
import java.util.LinkedList;
public class LinkedListExample {
public static void main(String[] args) {
LinkedList<Integer> list= new LinkedList<Integer>();
list.addFirst(1); // 가장 앞에 데이터를 추가
list.addLast(2); // 가장 뒤에 데이터 추가
list.add(3); // 데이터 추가
list.add(1,10); // 1번쨰 index에 데이터 10추가
}
}
package me.whiteship.livestudy.Collections;
import java.util.Arrays;
import java.util.LinkedList;
public class LinkedListExample {
public static void main(String[] args) {
LinkedList<Integer> list= new LinkedList<Integer>(Arrays.asList(1,2,3,4,5));
list.removeFirst(); // 가장 앞의 데이터 제거
list.removeLast(); // 가장 뒤의 데이터 제거
list.remove(); // index 생략시 0번째 index 제거
list.remove(1); // 1번째 index 제거
list.clear(); // 모든 값 제거
}
}
LinkedList<Integer> list= new LinkedList<Integer>(Arrays.asList(1,2,3,4,5));
System.out.println(list.size());
LinkedList<Integer> list= new LinkedList<Integer>(Arrays.asList(1,2,3,4,5));
System.out.println(list.get(0)); // 0번째 index 출력
System.out.println();
for (Integer integer : list) { // for문을 이용한 전체 출력
System.out.println(list);
}
Iterator iterator = list.iterator();
while(iterator.hasNext()){ // iterator를 이용한 전체 출력
System.out.println(iterator.next());
}
LinkedList<Integer> list= new LinkedList<Integer>(Arrays.asList(1,2,3,4,5));
System.out.println(list.contains(1)); // true 출력
System.out.println(list.indexOf(3)); // 2 출력
package me.whiteship.livestudy.Collections;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class App {
public static void main(String[] args) {
//ArrayList에 대한 타입 추론
List<Integer> list = Arrays.asList(3,2,1,4,5,6,6);
//또는 다음과 같이 선언가능
// List<Integer> list = new ArrayList<>();
// list.add(element);
for (Integer integer : list) {
System.out.println(integer);
}
}
}
output
3
2
1
4
5
6
6
예제코드
package me.whiteship.livestudy.Collections;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class App {
public static void main(String[] args) {
// natural order로 sorting
List<String> list = createList();
list.sort(null);
list.forEach((i)-> System.out.println(i));
System.out.println();
// 람다를 사용하여 sorting
List<String> list1 = createList();
list1.sort((s1,s2)->s1.compareToIgnoreCase(s2)); // 대소문자 구분없이 정렬
list1.forEach((i)-> System.out.println(i));
System.out.println();
// 메서드참조를 사용하여 sorting
List<String> list2 = createList();
list2.sort(String::compareToIgnoreCase);
list2.forEach(System.out::println);
}
private static List<String> createList(){
return Arrays.asList("ios","android","apple","samsung");
}
}
output
android
apple
ios
samsung
android
apple
ios
samsung
android
apple
ios
samsung
package me.whiteship.livestudy.Collections;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class App {
public static void main(String[] args) {
List<String> list = createList();
list.removeIf(s-> s.toLowerCase().contains("x"));
list.forEach(System.out::println);
}
private static List<String> createList(){
List<String> newList = new ArrayList<>();
newList.addAll(Arrays.asList("iPhone","Ubuntu","Andriod","MAC OS X"));
return newList;
}
}
output
iPhone
Ubuntu
Andriod
HashMap<String,String> hashMap = new HashMap<String,String>(); // HashMap 생성
HashMap<String,String> hashMap1 = new HashMap<>(); // new에서 타입 파라미터 생략가능
HashMap<String,String> hashMap2 = new HashMap<>(hashMap); // map의 모든 값을 가진 HashMap 생성
HashMap<String,String> hashMap3 = new HashMap<>(10); // 초기 용량 지정
HashMap<String,String> hashMap4 = new HashMap<>(10,0.7f); // 초기 용량 지정, load factor 지정
HashMap<String,String> hashMap5 = new HashMap<String,String>(){{put("a","b");}
}; // 초기값 지정
★★★해당내용참고링크
HashMap<Integer,String> hashMap = new HashMap<>(); // HashMap 생성
hashMap.put(1,"사과");
hashMap.put(2,"사과");
hashMap.put(3,"바나나");
HashMap<Integer,String> hashMap = new HashMap<Integer,String>(){{
put(1,"사과");
put(2,"사과");
put(3,"바나나");
}};
hashMap.remove(1); // key값 1 제거
hashMap.clear(); // 모든 값 제거
package me.whiteship.livestudy.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HashMapExample {
public static void main(String[] args) {
HashMap<Integer,String> hashMap = new HashMap<Integer,String>(){{
put(1,"사과");
put(2,"사과");
put(3,"바나나");
}};
System.out.println(hashMap); // 전체출력
System.out.println(hashMap.get(1)); // 키값1 출력
System.out.println();
// entrySet() 활용
// for문 사용
for (Map.Entry<Integer, String> integerStringEntry : hashMap.entrySet()) {
System.out.println(integerStringEntry.getKey() + " " + integerStringEntry.getValue());
}
System.out.println();
// iterator 사용
Iterator<Map.Entry<Integer,String>> entryIterator = hashMap.entrySet().iterator();
while(entryIterator.hasNext()){
Map.Entry<Integer,String> map = entryIterator.next();
System.out.println(map.getKey() + " " + map.getValue());
}
System.out.println();
// KeySet() 활용
// for문 사용
for (Integer integer : hashMap.keySet()) {
System.out.println(integer + " " + hashMap.get(integer));
}
System.out.println();
// iterator 사용
Iterator<Integer> iterator = hashMap.keySet().iterator();
while(iterator.hasNext()){
int key = iterator.next();
System.out.println(key + " " + hashMap.get(key));
}
}
}
TreeMap<Integer,String> treeMap1 = new TreeMap<Integer,String> (); // TreeMap 생성
TreeMap<Integer,String> treeMap2 = new TreeMap<> (); // new에서 파라미터 생략가능
TreeMap<Integer,String> treeMap3 = new TreeMap<> (treeMap1); // treeMap1의 모든값을 가진 TreeMap 생성
TreeMap<Integer,String> treeMap4 = new TreeMap<Integer,String>(){{ // 초기값 설정
put(1,"사과");
put(2,"사과");
put(3,"바나나");
}};
TreeMap<Integer,String> treeMap1 = new TreeMap<Integer,String> (); // TreeMap 생성
treeMap1.put(1,"사과");
treeMap1.put(2,"사과");
treeMap1.put(3,"바나나");
TreeMap<Integer,String> treeMap = new TreeMap<Integer,String>(){{
put(1,"사과");
put(2,"사과");
put(3,"바나나");
}};
treeMap.remove(1); // key값 1제거
treeMap.clear(); // 모든 값 제거
TreeMap<Integer,String> treeMap = new TreeMap<Integer,String>(){{
put(1,"사과");
put(2,"사과");
put(3,"바나나");
}};
System.out.println(treeMap); // 전체출력
System.out.println(treeMap.get(1)); // key값 1의 value 출력
System.out.println(treeMap.firstEntry()); // 최소 entry 출력 : 1,사과
System.out.println(treeMap.firstKey()); // 최소 key 출력 : 1
System.out.println(treeMap.lastEntry()); // 최대 entry 출력 : 3,바나나
System.out.println(treeMap.lastKey()); // 최대 key 출력 : 3
output
{1=사과, 2=사과, 3=바나나}
사과
1=사과
1
3=바나나
3
TreeMap<Integer,String> treeMap = new TreeMap<Integer,String>(){{
put(1,"사과");
put(2,"사과");
put(3,"바나나");
}};
//entrySet() 활용
//for문 활용
for (Map.Entry<Integer, String> integerStringEntry : treeMap.entrySet()) {
System.out.println(integerStringEntry.getKey()+ " " + integerStringEntry.getValue());
}
System.out.println();
//Iterator 활용
Iterator<Map.Entry<Integer,String>> iterator = treeMap.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<Integer,String> entry = iterator.next();
System.out.println(entry.getKey()+ " "+ entry.getValue());
}
System.out.println();
//keySet() 활용
//for문 활용
for (Integer integer : treeMap.keySet()) {
System.out.println(integer + " " + treeMap.get(integer));
}
System.out.println();
//iterator 활용
Iterator<Integer> iterator1 = treeMap.keySet().iterator();
while(iterator1.hasNext()){
int key = iterator1.next();
System.out.println(key + " " + treeMap.get(key));
}
`output
1 사과
2 사과
3 바나나
1 사과
2 사과
3 바나나
1 사과
2 사과
3 바나나
1 사과
2 사과
3 바나나
package me.whiteship.livestudy.Collections;
import java.util.HashMap;
import java.util.Map;
public class App {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
fillData(map);
map.put("Python","joa");
map.forEach((k,v)-> System.out.format("%s %s%n", k , v));
System.out.println();
map.remove("IOS");
map.forEach((k,v)-> System.out.format("%s %s%n", k , v));
}
private static void fillData(Map<String,String> map){
map.put("Android","SamSung");
map.put("IOS","Apple");
map.put("JAVA","Oracle");
}
}
output
JAVA Oracle
IOS Apple
Android SamSung
Python joa
JAVA Oracle
Android SamSung
Python joa
package me.whiteship.livestudy.Collections;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class App {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
fillData(map);
String[] strings = keyAsArray(map);
for (String string : strings) {
System.out.print(string+" ");
}
System.out.println();
List<String> list = keyAsList(map);
list.forEach(s -> System.out.print(s+ " "));
}
private static void fillData(Map<String,String> map){
map.put("Android","SamSung");
map.put("IOS","Apple");
map.put("JAVA","Oracle");
map.put("Python","Rossum");
}
private static String[] keyAsArray(Map<String,String> map){
return map.keySet().toArray(new String[map.keySet().size()]);
}
private static List<String> keyAsList(Map<String,String> map){
List<String> newList = new ArrayList<String>(map.keySet());
return newList;
}
}
output
JAVA IOS Android Python
JAVA IOS Android Python
package me.whiteship.livestudy.Collections;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class App {
public static void main(String[] args) {
Map<String,String> map = createMap();
map.put("NAVER",map.getOrDefault("qweqwe","helllo"));
map.put("NAVER2",map.getOrDefault("Android","helllo"));
map.forEach((k,v)-> System.out.println(k+ " "+ v + " "));
}
private static Map<String,String> createMap(){
Map<String,String> map = new HashMap<>();
map.put("Android","SamSung");
map.put("IOS","Apple");
map.put("JAVA","Oracle");
map.put("Python","Rossum");
return map;
}
}
output
JAVA Oracle
NAVER2 SamSung
NAVER helllo
IOS Apple
Android SamSung
Python Rossum
package me.whiteship.livestudy.Collections;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class App {
public static void main(String[] args) {
Map<String,String> map = createMap();
String value = map.computeIfAbsent("JAVA", it->"good");
System.out.println(value);
value = map.computeIfAbsent("Java", it->"good");
System.out.println(value);
System.out.println();
map.forEach((k,v)-> System.out.println(k+ " "+ v + " "));
}
private static Map<String,String> createMap(){
Map<String,String> map = new HashMap<>();
map.put("Android","SamSung");
map.put("IOS","Apple");
map.put("JAVA","Oracle");
map.put("Python","Rossum");
return map;
}
}
output
Oracle
good
JAVA Oracle
Java good
IOS Apple
Android SamSung
Python Rossum
또한 set은 객체를 중복해서 저장할 수 없고 하나의 중복 저장이 안되기에 null값도 하나만 저장할수있다.
대표적으로 HashSet과 TreeSet 클래스가 있다.
HashSet 클래스를 보면 ArrayList와 마찬가지로 동기화를 제공하지 않는다. 또한 추가되는 요소들의 순서도 보장하지 않는다.
Set에 추가되는 요소의 순서를 부여하기 위해서는 JDK1.4버전부터 도입된 LinkedHashSet이 있다. 이 클래스의 생성자를 살펴보면 HashSet 클래스와는 조금 다른것을 알 수 있다.
HashSet<Integer> set1 = new HashSet<Integer>(); // HashSet 생성
HashSet<Integer> set2 = new HashSet<>(); // new에서 타입 파라미터 생략가능
HashSet<Integer> set3 = new HashSet<Integer>(set1); // set1의 모든 값을 가진 HashSet 생성
HashSet<Integer> set4 = new HashSet<Integer>(10); // 초기 용량 지정
HashSet<Integer> set5 = new HashSet<Integer>(10,0.7f); // 초기용량,load factor 지정
HashSet<Integer> set6 = new HashSet<Integer>(Arrays.asList(1,2,3)); // 초기값 지정
HashSet<Integer> set = new HashSet<Integer>(); // HashSet 생성
set.add(1);
set.add(2);
set.add(3);
set.add(1); // 컴파일 오류나 런타임오류가 발생하지는 않는다
HashSet<Integer> set = new HashSet<Integer>(Arrays.asList(1,2,3)); // HashSet 생성
set.remove(1); // 값 1 제거
set.clear(); // 모든 값 제거
HashSet<Integer> set = new HashSet<Integer>(Arrays.asList(1,2,3));//HashSet생성
System.out.println(set.size());//set 크기 : 3
HashSet<Integer> set = new HashSet<Integer>(Arrays.asList(1,2,3)); // HashSet 생성
System.out.println(set);
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
HashSet<Integer> set = new HashSet<Integer>(Arrays.asList(1,2,3));//HashSet생성
System.out.println(set.contains(1)); //set내부에 값 1이 있는지 check : true
TreeSet<Integer> treeSet1 = new TreeSet<Integer>(); // TreeSet 생성
TreeSet<Integer> treeSet2 = new TreeSet<>(); // new에서 타입 파라미터 생략가능
TreeSet<Integer> treeSet3 = new TreeSet<Integer>(treeSet1); // treeSet1의 모든 값을 가진 treeSet 생성
TreeSet<Integer> treeSet4 = new TreeSet<Integer>(Arrays.asList(1,2,3)); // 초기값 지정
TreeSet<Integer> set = new TreeSet<Integer>();//TreeSet생성
set.add(7); //값추가
set.add(4);
set.add(9);
set.add(1);
set.add(5);
TreeSet<Integer> set = new TreeSet<Integer>();//TreeSet생성
set.remove(1);//값 1 제거
set.clear();//모든 값 제거
TreeSet<Integer> set = new TreeSet<Integer>(Arrays.asList(1,2,3));//초기값 지정
System.out.println(set.size());//크기 : 3
TreeSet<Integer> set = new TreeSet<Integer>(Arrays.asList(4,2,3));//초기값 지정
System.out.println(set); //전체출력 [2,3,4]
System.out.println(set.first());//최소값 출력
System.out.println(set.last());//최대값 출력
System.out.println(set.higher(3));//입력값보다 큰 데이터중 최소값 출력 없으면 null
System.out.println(set.lower(3));//입력값보다 작은 데이터중 최대값 출력 없으면 null
Iterator iter = set.iterator(); // Iterator 사용
while(iter.hasNext()) {//값이 있으면 true 없으면 false
System.out.println(iter.next());
}
output
[2, 3, 4]
2
4
4
2
2
3
4
/* LinkedHashSet Class */
public class LinkedHashSet<E> extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
...
public LinkedHashSet() {
super(16, .75f, true);
}
...
}
/* 여기서 부모 클래스의 생성인 super, 즉 HashSet의 오버로딩 생성자로 진입해보면 */
public class HashSet<E> extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
...
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
...
}
package me.whiteship.livestudy.Collections;
import java.util.*;
public class App {
public static void main(String[] args) {
// 오름차순으로 정렬하는 TreeSet
TreeSet<Integer> treeSet = new TreeSet<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1<o2 ? -1 : ((o1==o2) ? 0:1);
}
});
treeSet.add(3); treeSet.add(1); treeSet.add(2);
Iterator<Integer> iterator = treeSet.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println();
// Using JAVA 8
TreeSet<Integer> treeSet1 = new TreeSet<>(
((o1, o2) -> o1<o2 ? -1: (o1==o2 ? 0:1))
);
treeSet1.add(3);
treeSet1.add(1);
treeSet.add(2);
treeSet.forEach(System.out::println);
}
}
output
1
2
3
1
2
3
output
java.util.Collections의 클래스는 컬렉션을 다루는 작업에 유용한 기능들을 제공해준다.
Collections.copy(list,list): 복사본 만들기
Collections.reverse(list): 역순으로 정렬하기
Collections.shuffle(list): 무작위로 섞기
Collections.sort(list): 정렬하기
package me.whiteship.livestudy.Collections;
import java.util.*;
public class App {
public static void main(String[] args) {
List<String> list = createList();
List<String> list1 = new ArrayList<>();
Collections.shuffle(list);
list.forEach(System.out::println);
System.out.println();
Collections.sort(list);
list.forEach(System.out::println);
System.out.println();
Collections.reverse(list);
list.forEach(System.out::println);
System.out.println();
Collections.copy(list,list1);
list1.forEach(System.out::println);
System.out.println();
}
private static List<String> createList(){
List<String> list = new ArrayList<>();
list.add("hello");
list.add("hi");
list.add("good");
return list;
}
}
output
good
hi
hello
good
hello
hi
hi
hello
good
package me.whiteship.livestudy.Collections;
import java.util.*;
public class App {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(3,2,1,5,4,6,7);
Collections.sort(list);
list.forEach(System.out::println);
}
}
output
1
2
3
4
5
6
7
package me.whiteship.livestudy.Collections;
import java.util.*;
public class App {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(3,2,1,5,4,6,7);
Collections.sort(list,((o1, o2) -> o1>o2 ? -1 : (o1==o2)? 0:1 ));
list.forEach(System.out::println);
}
}
output
7
6
5
4
3
2
1
다음 벡터를 살펴보자.
synchronized
키워드가 있다. List<String> list = Collections.synchronizedList(new ArrayList<String>());
list.add("hi");
list.add("hallo");
list.add("hello");
synchronized (list){
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
HashSet<String> hashSet = new HashSet<>();
Set<String> set = Collections.synchronizedSet(hashSet);
java 1.5 버전 부터 등장한 java.util.concurrent
패키지는 다양한 동시성 기능을 제공한다.
HashMap에 동기화 기능을 적용한 ConcurrentMap이 여기에 속해있다.
동기화를 위해 SynchronizedMap을 사용할수있지만 지금 살펴볼 ConcurrentMap의 성능이 더 좋다.
그 이유는 바로 동기화 블록 범위에 있다.
ConcurrentMap은 동기화를 진행하는 경우 Map 전체에 락(Lock)을 걸지않고 Map을 여러 조각으로 나누어서 부분적으로 락을 거는 형태로 구현되어 있기 때문이다.
이러한 특징은 멀티쓰레드 환경에서 더 효율적인 성능을 보인다. 테스트를 해보자
package me.whiteship.livestudy.Collections;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.IntStream;
public class ConcurrentExample {
private static final int MAX_THREAD_POOL_SIZE = 5;
private static final int MAX_TEST_COUNT = 5;
private static final int MAX_OPERATE_COUNT = 100_000;
public static Map<String,Integer> testHashTable = null;
public static Map<String,Integer> testSyncMap = null;
public static Map<String,Integer> testConcMap = null;
public static void collectionPerformTest() throws InterruptedException{
testHashTable = new Hashtable<>();
runSomethinTest(testHashTable);
testConcMap = new ConcurrentHashMap<>();
runSomethinTest(testConcMap);
testSyncMap = Collections.synchronizedMap(new HashMap<>());
runSomethinTest(testSyncMap);
}
private static void runSomethinTest(Map<String, Integer> testTarget) throws InterruptedException {
System.out.println("Target Class" + testTarget.getClass());
long testAverageTime = 0L;
for (int testCount = 0; testCount < MAX_TEST_COUNT; testCount++) {
long testStartTime = System.nanoTime();
ExecutorService executorService = Executors.newFixedThreadPool(MAX_THREAD_POOL_SIZE);
// rangeClosed 는 마지막 값을 포함하여 Looping
IntStream.range(0,MAX_THREAD_POOL_SIZE).forEach(count -> executorService.execute(()->{
for (int i = 0; i < MAX_OPERATE_COUNT; i++) {
Integer randomValue =(int) Math.ceil(Math.random()*MAX_OPERATE_COUNT);
testTarget.put(String.valueOf(randomValue), randomValue);
}
}));
// 수행 종료. 이미 수행중인 것은 마저 진행하지만 새 작업은 허용하지 않는다.
executorService.shutdown();
// shutdown 이후에 모든 작업이 종료되기까지 대기한다.
executorService.awaitTermination(Long.MAX_VALUE,TimeUnit.DAYS);
long testEndTime = System.nanoTime();
long testTime = (testEndTime - testStartTime) / 1_000_000L;
testAverageTime += testTime;
System.out.println(testTarget.getClass()+"'s Test" + (testCount-1)+":"+testTime);
}
System.out.println(testTarget.getClass()+"'s average time is "+ testAverageTime);
System.out.println();
}
public static void main(String[] args) throws InterruptedException {
collectionPerformTest();
}
}
output
arget Classclass java.util.Hashtable
class java.util.Hashtable's Test-1:376
class java.util.Hashtable's Test0:209
class java.util.Hashtable's Test1:168
class java.util.Hashtable's Test2:218
class java.util.Hashtable's Test3:194
class java.util.Hashtable's average time is 1165
Target Classclass java.util.concurrent.ConcurrentHashMap
class java.util.concurrent.ConcurrentHashMap's Test-1:165
class java.util.concurrent.ConcurrentHashMap's Test0:132
class java.util.concurrent.ConcurrentHashMap's Test1:107
class java.util.concurrent.ConcurrentHashMap's Test2:115
class java.util.concurrent.ConcurrentHashMap's Test3:110
class java.util.concurrent.ConcurrentHashMap's average time is 629
Target Classclass java.util.Collections$SynchronizedMap
class java.util.Collections$SynchronizedMap's Test-1:287
class java.util.Collections$SynchronizedMap's Test0:207
class java.util.Collections$SynchronizedMap's Test1:221
class java.util.Collections$SynchronizedMap's Test2:201
class java.util.Collections$SynchronizedMap's Test3:226
class java.util.Collections$SynchronizedMap's average time is 1142