(향상된)배열. 배열을 감싼 클래스(물리적 구조 상). 배열의 길이가 가변.(실행중 늘리거나 줄이는 게 가능). 배열을 사용 목적에 따라 사용법이나 구조를 특화시켜 미리 제공.
ArrayList, LinkedList, Stack, (Queue), (vector)
HashSet, TreeSet
HashMap, TreeMap, (Properties)
ArrayList(C)->List(I)->Collection(I)
사용빈도가 가장 높음. 순수 배열과 구조가 가장 유사함(그래서 사용빈도가 높음)
첨자(Index)를 사용해서 요소(element)에 접근/제어 -> 순수배열과 동일
// Object 버전
ArrayList list1=new ArrayList();
list1.add(100);
System.out.println((int)list1.get(0)*2);
// Generic 버전(다양한 자료형을 담을 수 있고, 끝없이 담을 수 있음)
ArrayList<Integer> list2=new ArrayList<Integer>();
list2.add(100);
System.out.println(list2.get(0)*2);
//ArrayList 사용법
ArrayList<String> list=new ArrayList<String>();
// 1. 요소 추가하기
// boolean add(T value)
// 배열의 맨 마지막에 추가하기(append)
list.add("빨강");
list.add("파랑");
list.add("노랑");
list.add("검정");
list.add("주황");
// 2. 요소의 개수
// int size()
// 배열의 맨 마지막에 추가하기(append)
System.out.println(list.size());
// 3. 요소의 접근
// T get(int index)
System.out.println(list.get(0));
System.out.println(list.get(1));
System.out.println(list.get(2));
System.out.println(list.get(list.size()-1));
// 4. 요소의 수정
// T set(int index, T element) -> 수정되기 전 값을 반
System.out.println(list.get(0));
String temp=list.set(0, "red");
System.out.println(list.get(0));
// 5. 요소의 삭제(주의해야 함!!!)
// 순수 배열은 요소 삭제가 불가능 -> 방 개수를 줄이는 것이 불가능!
// T remove(int index)
// Left Shift 발생!!!(요소 하나가 빠지면 그 칸 채우기 위해 왼쪽으로 이동)
// boolean remove(T element)와 같이 쓰면 지웠는지 안 지웠는지 여부가 boolean으로 반환
System.out.println(list.size());
System.out.println(list.remove(0));
System.out.println(list.size());
// 6. 요소의 추가(주의해야 함!!!)
// boolean add(int index, T element)
// 배열의 넣고 싶은 위치에 추가하기 -> insert 모드
// Light Shift 발생!!!(요소 하나가 더해지면 그 요소가 들어갈 칸 확보하기 위해 오른쪽으로 이동)
for(int i=0;i<list.size();i++) {
System.out.printf("list[%d]= %s\n", i, list.get(i));
}
list.add(1, "녹색");
for(int i=0;i<list.size();i++) {
System.out.printf("list[%d]= %s\n", i, list.get(i));
}
// 7. 탐색
// for문
for(int i=0;i<list.size();i++) {
System.out.printf("list[%d]= %s\n", i, list.get(i));
}
// 향상된 for문
for(String color:list) {
System.out.println(color);
}
// 8. 검색
// boolean contains(T values)
// int indexOf(T value)
// int lastIndexOf(t value)
System.out.println(list.contains("빨강"));
System.out.println(list.contains("파랑"));
if (list.contains("파랑")){
list.remove("파랑");
System.out.println("파랑 삭제");
}else {
System.out.println("파랑 없음");
}
System.out.println(list.indexOf("노랑"));
System.out.println(list.lastIndexOf("노랑"));
// 9. 덤프(dump) : 개발자용. 고객출력용 아님!
System.out.println(list.toString()); // toString()은 오버라이딩된 것!
// 10. 초기화
// 배열의 내용을 전부 지워버림.
// void clear()
list.clear(); // 아니면 list=new ArrayList<String>으로 변수만 재활용 하거나.(이렇게 되면 새로 ArrayList를 메모리에 만들어서 주소값만 바꿔주는 것. 낭비! 원래 연결되어있던 참조는 끊김.)
System.out.println(list.isEmpty()); // 비워있는지 확인하려면 isEmpty() 이용.
// 11. 정렬
// void sort(List<T> list)
// List<T> list
// List(인터페이스) : 부모 <- ArrayList(클래스) : 자식
Collections.sort(list); // 순차정렬, 순정렬, 오름차순
System.out.println(list);
Collections.reverse(list); // 순차정렬되어있는 것을 뒤집음. 위에서 오름차순으로 정렬했으므로 내림차순으로 정렬되는 결과.
System.out.println(list);
// 12. 부분 집합 추출
// List<T> subList(index fromIndex, index toIndex)
list.subList(fromIndex.toIndex)
private static void m1() {
// 순수배열
int[] nums1=new int[3]; // 타입과 길이 명시
// 초기화 or 요소 접근(첨자(index) 사용) -> Indexer(인덱서)
nums1[0]=100;
nums1[1]=200;
nums1[2]=300;
// 요소 접근(첨자(index) 사용)
System.out.println(nums1[0]);
for(int i=0;i<nums1.length;i++) {
System.out.println(nums1[i]);
}
// ArrayList
ArrayList nums2=new ArrayList();
nums2.add(100);
nums2.add(200);
nums2.add(300);
System.out.println(nums2.get(0));
// System.out.println(nums2.get(0)*2); 이런건 불가능. get되어서 나올 때 자료형이 어떤 것일지 모르기 때문.
// System.out.println((int)nums2.get(0)*2); 다운캐스팅하면 가능
for(int i=0;i<nums2.size();i++) {
System.out.println(nums2.get(i));
}
}
class Student{
private String name;
private int kor;
private int eng;
private int math;
public Student() {
this("", 0, 0, 0);
}
public Student(String name, int kor, int eng, int math) {
this.name=name;
this.kor=kor;
this.eng=eng;
if (math>=0 && math<=100) {
this.math=math;
}
}
public Student(int kor, int eng, int math) {
this("", kor, eng, math);
}
}
public class Ex71_ArrayList {
public static void main(String[] args) {
// JDK
ArrayList<Integer> list1=new ArrayList<Integer>();
// 만든 ArrayList
MyArrayList list2=new MyArrayList();
}
}
class MyArrayList{
private int[] list;
private int index; // 중요역할! 여태 넣은 데이터 수 & 지금 들어갈 마지막 방번호.
public MyArrayList() {
this.list=new int[4];
this.index=0;
}
public void add(int value) {
// 1. 어느 자리에 넣을 것인가
// 2. 꽉 찰 경우 어떻게 늘릴 것인가
this.list[index]=value;
index++;
// 더 이상 데이터를 넣을 방이 있는지? 없는지?
if (list.length==index) { // 넣을 방이 없다면
int[] temp=new int[this.list.length*2]; // 현재 리스트 길이의 2배 길이가 되는 리스트를 만들고,
for (int i=0; i<this.list.length;i++) { // 그 리스트에 각 요소를 깊은 복사해준다.
temp[i]=this.list[i];
}
this.list=temp; // 그리고 리스트를 교체.
}
}
public int get(int index) {
return this.list[index];
}
@Override
public String toString() {
String temp="";
temp+="[";
for(int i=0;i<this.index;i++) {
temp+=this.list[i]+", ";
}
temp=temp.substring(0, temp.length()-2);
temp+="]";
return temp;
}
}
아래와 같이 크기 지정이 가능하다. 그러나 이 지정된 크기보다 더 넣었을 경우는 크기가 doubling이 된다.
ArrayList<Integer> list3=new ArrayList<Integer>(1000);
for(int i=1;i<=1000;i++) {
list3.add(i);
}
크기보다 더 넣어서 크기가 doubling되었을 때, 쓸모없는 칸들을 버리는 방법은 아래와 같다. 자주 쓰면 안좋다. 길이가 더 이상 늘어나지 않는다고 확신할 때 사용할 것.
list3.trimToSize();