컬렉션 프레임워크 중 주요 클래스인 ArrayList, HashSet, TreeSet, HashMap 에 대해서 학습해보았다. 컬렉션 프레임워크는 자료구조를 다루는 방법이므로 꼭 알아두자.
ArrayList는 List 인터페이스를 구현한 클래스로 배열과 동일하게 연속된 메모리 공간을 사용하고 순서가 있고 중복을 허용한다는 특성을 가진다.
배열과의 차이점은 배열의 크기는 고정인 반면 ArrayList 의 크기는 가변적으로 변한다는 것이다.
내부적으로 저장이 가느한 메모리 용량(Capacity)이 있으며 현재 사용중인 공간의 크기(size) 가 있는데, 만약 현재 메모리 용량 이상을 저장하려 하면 더 큰 공간의 메모리를 새롭게 할당한다.
ArrayList list = new ArrayList<>();
ArrayList list = new ArrayList<>(8); // 초기 용량 세팅
ArrayList list = new ArrayList<>(Arrays.asList(1, 2, 3, 4)); // 초기 값 세팅
add() 를 이용해서 ArrayList에 값을 추가한다.
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("안녕");
list.add("안녕");
list.add(1, "하이");
System.out.print(list); //[안녕, 하이, 안녕]
}
}
list.add(Object) ==> list의 마지막 배열에 데이터 추가
list.add(int index , Object) ==> list의 index 자리에 데이터 추가
set() 를 사용해서 ArrayList의 값을 변경한다.
list.set(int index , Object) ==> list의 index 자리에 데이터 변경
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("하이");
list.add("하이");
list.add("하이");
System.out.println("초기값 : " + list); //[하이, 하이, 하이]
list.set(1, "안녕");
System.out.println("변경된 값 : " + list); //[하이, 안녕, 하이]
}
}
remove() 를 통해서 ArrayList 의 값을 삭제할 수 있다.
list.remove(int index) ==> index의 값 삭제 (데이터는 오른쪽에서 왼쪽으로 당겨진다)
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("하이");
list.add("하이");
list.add("하이");
System.out.println("초기값 : " + list); //[하이, 하이, 하이]
list.remove(1);
System.out.println("변경된 값 : " + list); //[하이, 하이]
}
}
HashSet은 Set 인터페이스를 구현한 클래스로 순서대로 입력되지 않고, 중복을 허용하지 않는다는 특징이 있다.
HashSet은 객체를 저장하기 전에 객체의 hashCode() 메서드를 호출해서 해시 코드를 얻은 다음 이미 저장되어 있는 객체들의 hashCode 와 비교하여 같은 hashCode가 있다면 equals() 메서드로 두 객체를 비교해서 true 가 나오면 같은 객체로 파악하고 중복 저장을 하지 않는다.
그래서 실제 HashSet을 사용할 때는, 니즈에 맞게 hashCode() 와 equals() 를 재정의하여 사용할 수 있다. (고객 ID 가 같으면 다른 고객이더라도 같은 고객으로 인식하게 한다 등등)
HashSet set = new HashSet
HashSet도 add() 를 추가하여 값을 추가하는데, 이 때 제네릭에 맞는 타입만 추가해준다.
set.add(value);
public class HashSetTest {
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.add(1);
// String
HashSet<String> set2 = new HashSet<String>();
set2.add("a");
set2.add("b");
set2.add("c");
set2.add("a");
}
}
set.remove(value) 를 통해서 원하는 값을 삭제 할 수 있다.
public class HashSetTest {
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<Integer>();
set.remove(1);
// String
HashSet<String> set2 = new HashSet<String>();
set2.remove("a");
}
}
public class HashSetTest {
public static void main(String[] args) {
// Integer
HashSet<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.add(1);
System.out.println("set의 크기 : " + set.size()); // set의 크기 : 3 * 중복 저장 안됨
// String
HashSet<String> set2 = new HashSet<String>();
set2.add("a");
set2.add("b");
set2.add("c");
set2.add("a");
System.out.println("set2의 크기 : " + set2.size()); //// set2의 크기 : 3 * 중복 저장 안됨
}
}
HashSet 출력하기
HashSet을 단순히 println으로 출력하는 경우 [1,2,3], [a,b,c] 형태로 출력하게 된다.
하나의 객체를 가져오고 싶을 때는 Iterator 를 통해서 가져올 수 있다.
import java.util.HashSet;
import java.util.Iterator;
public class HashSetTest {
public static void main(String[] args) {
// Integer
HashSet<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.add(1);
System.out.println("set의 값 : " + set); // set의 값 : [1,2,3]
// String
HashSet<String> set2 = new HashSet<String>();
set2.add("a");
set2.add("b");
set2.add("c");
set2.add("a");
System.out.println("set2의 값 : " + set2); // set2의 값 : [a,b,c]
// Integer 출력
// Iterator 는 collection 의 인터페이스이다.
// Boolean hasNext ==> 더 있나?
// next ==> 다음 반환
Iterator iter = set.iterator();
while(iter.hasNext()) {
System.out.print(iter.next() + " ");
} // 1 2 3
System.out.println("");
// String 출력
Iterator iter2 = set2.iterator();
while(iter2.hasNext()) {
System.out.print(iter2.next() + " ");
} // a b c
}
}
TreeSet 은 HashSet 과 마찬가지로 Set 인터페이스를 구현하고 있다. (Set 리모컨을 쓴다)
그래서 Set 이 가지고 있는 저장순서 유지x 와 객체 중복 저장이 안되는 성질을 가지고 있다.
HashSet과 다른 점은 TreeSet은 이진탐색트리(BinarySearchTree) 구조로 이루어져 있어 정렬과 검색에 장점이 있는 자료구조이다. (데이터 추가와 삭제에는 더 많은 시간이 소요된다)
이진탐색트리는 하나의 데이터를 기준으로 그 데이터보다 작으면 왼쪽 크면 오른쪽에 추가하는 방식으로 기본적으로 오름차순 (nature ordering)이다. 또한 생성자의 매개변수로 Comparator 객체를 입력하여 정렬 방식을 지정할 수 있다.
TreeSet set1 = new TreeSet<>();//new에서 타입 파라미터 생략가능
TreeSet set2 = new TreeSet(set1);//set1의 모든 값을 가진 TreeSet생성
TreeSet set3 = new TreeSet(Arrays.asList(1,2,3));//초기값 지정
** 선언 시 크기를 지정해 줄 수는 없다.
TreeSet의 값은 이진트리를 활용하여 추가가 된다. 위에서도 서술하였듯 처음 기준을 두고 그 기준보다 작으면 왼쪽, 크면 오른쪽으로 데이터를 정렬한다. add() 를 사용하게 되는데, add()로 추가한 값이 기존 TreeSet에 없으면 값을 추가한 뒤 True 를 반환하고, 값이 있다면 값을 추가하지 않고 false 를 반환한다.
TreeSet<Integer> set = new TreeSet<Integer>();//TreeSet생성
set.add(7); //값추가
set.add(4);
set.add(9);
set.add(1);
set.add(7); // false , 추가되지 않음
TreeSet 값 전체를 출력할 때는 Iterator 를 활용한다.
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());
}
HashMap 은 Map 인터페이스를 구현하였다는 점에서 위의 클래스(Collection 구현)들과는 다르다. Map은 Key와 Value로 구성된 Entry(한쌍) 객체를 저장하는 구조를 가지고 있다. 여기서 key와 value 는 모두 객체이며 value는 중복저장되지만 key는 중복저장되지 않는다. 기존의 key와 동일한 key로 값을 저장하면 기존의 value 대신 새로운 value 가 들어가게 된다.
HashMap은 Hashing을 사용하기 때문에 많은 양의 데이터를 검색하는데 있어서 뛰어난 성능을 보인다.
HashMap<String,String> map1 = new HashMap<>();//new에서 타입 파라미터 생략가능
HashMap<String,String> map2 = new HashMap<>(map1);//map1의 모든 값을 가진 HashMap생성
HashMap<String,String> map3 = new HashMap<>(10);//초기 용량(capacity)지정
HashMap<String,String> map4 = new HashMap<>(10, 0.7f);
//초기 capacity,load factor지정 (*총량 10 중 0.7 만큼이 차면 총량을 2배로 늘림)
HashMap<String,String> map5 = new HashMap<String,String>(){{//초기값 지정
put("a","b");
}};
HashMap은 put를 통해 값을 추가해주고 map.put(Key, Value) 형태로 추가해준다.
HashMap<Integer,String> map = new HashMap<>();//new에서 타입 파라미터 생략가능
map.put(1,"사과"); //값 추가
map.put(2,"바나나");
map.put(3,"포도");
map.remove(key) 를 통해서 해당 정보를 삭제할 수 있음 (오직 key로만 삭제 가능)
또한 map.clear() 를 통해서 모든 값을 제거할 수 있다.
HashMap<Integer,String> map = new HashMap<Integer,String>(){{//초기값 지정
put(1,"사과");
put(2,"바나나");
put(3,"포도");
}};
map.remove(1); //key값 1 제거
map.clear(); //모든 값 제거
HashMap<Integer,String> map = new HashMap<Integer,String>(){{//초기값 지정
put(1,"사과");
put(2,"바나나");
put(3,"포도");
}};
//entrySet().iterator()
Iterator<Entry<Integer, String>> entries = map.entrySet().iterator();
while(entries.hasNext()){
Map.Entry<Integer, String> entry = entries.next();
System.out.println("[Key]:" + entry.getKey() + " [Value]:" + entry.getValue());
}
//[Key]:1 [Value]:사과
//[Key]:2 [Value]:바나나
//[Key]:3 [Value]:포도
//keySet().iterator()
Iterator<Integer> keys = map.keySet().iterator();
while(keys.hasNext()){
int key = keys.next();
System.out.println("[Key]:" + key + " [Value]:" + map.get(key));
}
//[Key]:1 [Value]:사과
//[Key]:2 [Value]:바나나
//[Key]:3 [Value]:포도
Iterator 를 통해서 HashMap 의 값을 출력해줄 수 있는데, entrySet을 통해서 쌍을 데리고와서 출력을 해줄 건지, keySet을 통해서 Key 값을 가져와서 value를 불러 출력해주는 방법등이 있다.
출처
https://crazykim2.tistory.com/558
https://coding-factory.tistory.com/556