List - Vector - LinkedList

오늘·2021년 4월 4일
0

Java

목록 보기
37/42

List컬렉션

-List는 객체를 일렬로 늘어놓은 구조
-객체를 인덱스로 관리
: = 순서 유지 가능, 중복으로 객체 저장 가능
: 중간에 삭제가 있다면 뒤에서 당겨 채움
: 인덱스로 객체를 검색, 삭제할 수 있는 기능이 제공
-단, 삽입 삭제가 빈번한 경우에는 사용 비추천
-null도 저장이 가능한데, 이 경우 해당 인덱스는 객체를 참조하지 않는다.


ArrayList

  • List 인터페이스의 구현 클래스
  • 배열과 ArrayList는 인덱스로 객체관리한다는 점에서 유사하지만,
    배열은 생성시 크기가 계속 고정되는데 반하여 ArrayList는 저장용량을 초과시 자동으로 저장 용량이 늘어난다.
new ArrayList<사용할 타입>(객체를 저장할 수 있는 용량)
// String 타입을 30개 저장할 수 있게끔 생성
List list = new ArrayList<String>(30);
// 하지만 리스트는 자동으로 저장 용량이 늘어나기 때문에
// 크기를 정하지 않고도 생성 가능하다
List list1 = new ArrayList<String>();

ArrayList 생성

// List list = new List() -> 불가. List는 인터페이스이기 때문에
// 다형성을 이용해 하위에 있는 ArrayList로 객체 생성해준다
// ArrayList<리턴형태>
// 아래 예시는 Integer형태의 값을 저장하는 ArrayList를 만들것이라는 선언
List list = new ArrayList<Integer>();

값 저장은 .add

list.add(10);
list.add(20);
// 중복으로 넣는것도 가능하다
list.add(30);
list.add(30);

검색할 내용은 .contains / 값 삭제는 .remove()

  • list에 귤이 있는지 검색
  • 귤이 있다면 2번 인덱스의 값을 삭제해라
if (list.contains("귤")) {
	System.out.println("가게에 귤이 있습니다");
	list.remove(2);
} else {
	System.out.println("가게에 귤은 없습니다");
}

이미 해당 인덱스에 값이 있어도 삽입 가능

list.add(2, 80);
System.out.println("2번 인덱스가 다른 값으로 채워지고 값이 밀리는 것을 확인");
for(int i=0; i<list.size(); i++) {
	System.out.println("index " + i + "=" + list.get(i));
}

리스트 크기를 확인하고 싶다 .size()

System.out.println("ArrayList의 크기 : " + list.size());

사용해보기 01

// 사용하려면 객체 생성부터
// List list = new List() -> 불가. List는 인터페이스이기 때문에
// 다형성을 이용해 하위에 있는 ArrayList로 객체 생성해준다
// ArrayList<리턴형태>
List list = new ArrayList<Integer>();
		
// 값 넣어주기
list.add(10);
list.add(20);
// 중복 가능
list.add(30);
list.add(30);
		
System.out.println("ArrayList의 크기 : " + list.size());
// 2번 인덱스에 있는 값을 출력하겠다
System.out.println("2번 인덱스의 값 : " + list.get(2));
		
System.out.println();
		
// 0번 인덱스의 값을 지우겠다
list.remove(0);
// 확인
System.out.println("값을 지우면 빈 공간은 알아서 뒤에 값이 땡겨져와 채운다");
for(int i=0; i<list.size(); i++) {
	System.out.println("index " + i + "=" + list.get(i));
}
		
System.out.println();

// 2번 인덱스에 값 80을 넣어주겠다
list.add(2, 80);
System.out.println("2번 인덱스가 다른 값으로 채워지고 값이 밀리는 것을 확인");
for(int i=0; i<list.size(); i++) {
	System.out.println("index " + i + "=" + list.get(i));
}
		
		
System.out.println();
		
// 사과 배 귤 바나나
// 를 넣고 귤이 있는지 확인
List list1 = new ArrayList<String>();
list1.add("사과");
list1.add("배");
list1.add("귤");
list1.add("바나나");
		
// 있는지 확인하려면
// .contains(검색할 내용)
if (list1.contains("귤")) {
	System.out.println("가게에 귤이 있습니다");
	list1.remove(2);
} else {
	System.out.println("가게에 귤은 없습니다");
}
// 위 코드에서 귤이 있다면 귤이 있는 인덱스2번을 지우도록 했으니
// 이 코드가 실행되면 else의 실행 코드가 수행된다
if (list1.contains("귤")) {
	System.out.println("가게에 귤이 있습니다");
	list1.remove(2);
} else {
	System.out.println("가게에 귤은 없습니다");
}
				
System.out.println();
		
// 배열에 있는 내용을 모두 삭제
System.out.println("clear 하기 전 크기 : " + list.size());
list.clear();
System.out.println("clear() 후 크기 : " + list.size());
		
// 리스트가 비워져있는지 확인하려면
// .isEmpty()
boolean listE = list.isEmpty();
System.out.println(listE);
		
System.out.println();

// new ArrayList<사용할 타입>(객체를 저장할 수 있는 용량);
// new ArrayList<Integer>(30); <= Integer형태의 객체를 30개 저장할 수 있는 용량을 가진다
List list2 = new ArrayList<Integer>();
list2.add("사과");
list2.add("배");
list2.add("귤");
list2.add("바나나");
list2.add("귤");
		
// "귤"이 여러개라면 마지막 인덱스를 출력한다
System.out.println("마지막으로 귤이 들어있는 인덱스 : " + list.indexOf("귤"));
// 2번인덱스 3번 인덱스 내용 뽑기
System.out.println(list2.subList(2, 4));

실행 결과


사용해보기 02

List<String> list = new ArrayList<String>();

// 객체를 순서대로 저장해준다
list.add("Java");
list.add("JDBC");
list.add("Servlet/JSP");
list.add(2, "Database");
list.add("iBATIS");

// 저장된 총 개수를 얻기
int size = list.size();
System.out.println("총 객체수: " + size);
System.out.println();

// 2번 인덱스의 객체 얻기
String skill = list.get(2);
System.out.println("2: " + skill);
System.out.println();

// 저장된 총 갯수만큼 돌아
// 배열의 내용 뽑아오기
for (int i = 0; i < list.size(); i++) {
	String str = list.get(i);
	System.out.println(i + ":" + str);
}
System.out.println();

// 값 지워주기
list.remove(2);
list.remove(2);
list.remove("iBATIS");

// 지워진 인덱스는 뒤에있던 값들이 알아서 채워주는 모습
for (int i = 0; i < list.size(); i++) {
	String str = list.get(i);
	System.out.println(i + ":" + str);
}
		
System.out.println();

// 이터레이터 사용해보기
// 리스트 안에있는 모든 자료들이 출력되었다
Iterator<String> it = list.iterator();
// it에 다음 값이 있다면 true / 없다면 false
// 토큰과 비슷한 느낌..?
while(it.hasNext()) {
	System.out.println(it.next());
}

실행 결과


사용해보기 03

// 학생 클래스
// 문제에서 주어진 내용을 배열리스트에 넣기
// 2018 학번이 있는지 검색하기

public class A_ArrayListTest {
	public static void main(String[] args) {		
		List<Student> list = new ArrayList<Student>();
		int hakbun = 0;
		
		// 값 넣는 곳에 객체 생성
		list.add(new Student(2021, "홍길동"));
		list.add(new Student(2020, "최수진"));
		list.add(new Student(2018, "박현미"));
		list.add(new Student(2021, "최수영"));

		
		for(int i=0; i<list.size(); i++) {
			if (list.get(i).num == 2018) {
				System.out.println(list.get(i).num);
				hakbun += 1;
			} else {
				continue;
			}
		}

		System.out.println("찾으시는 학번에 해당하는 인물은 " + hakbun + "명입니다");
	}
}

class Student{
	int num;
	String name;
	
	public Student(int num, String name) {
		this.num = num;
		this.name = name;
	}
}

실행 결과

2018
찾으시는 학번에 해당하는 인물은 1명입니다

vector

ArrayList와 동일한 내부 구조를 가지고 있다.

// 생성 모양도 같다
List<E> list = new Vector<E>();

Vector 와 List의 차이점

Vector는 동기화된 메소드로 구성되어있기 때문에 멀티 스레드가 동시에 이 메소드들을 실행할 수 없고, 하나의 스레드가 실행을 완료해야만 다른 스레드를 실행할 수 있다. 그래서 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제 가능 하다는 것이다

public class B_VectorEx {
	public static void main(String[] args) {
		List<Board> list = new Vector<Board>();
		
		list.add(new Board("제목1", "내용1", "글쓴이1"));
		list.add(new Board("제목2", "내용2", "글쓴이2"));
		list.add(new Board("제목3", "내용3", "글쓴이3"));
		list.add(new Board("제목4", "내용4", "글쓴이4"));
		list.add(new Board("제목5", "내용5", "글쓴이5"));
		
		// 내용 모두 출력해보기
		Iterator<Board> it = list.iterator();
		while(it.hasNext()) {
			Board board = it.next();
			System.out.println(board.subject + "\t" + board.content + "\t" + board.writer);
		}
		
		System.out.println();
		
		// 먼저 2번 인덱스를 지워서 "제목3"번 내용이 사라짐
		list.remove(2);
		// 한칸씩 당겨와서 새롭게 인덱스 3번이 된 "제목 5"번 내용이 사라지게 된다
		list.remove(3);
		
		for(int i=0; i<list.size(); i++) {
			Board board = list.get(i);
			System.out.println(board.subject + "\t" + board.content + "\t" + board.writer);
		}
	}
}


class Board {
	String subject;
	String content;
	String writer;
	
	public Board(String subject, String content, String writer) {
		this.subject = subject;
		this.content = content;
		this.writer = writer;
	}
}

사실 코드에서

list.remove(2);
list.remove(3);

결과를 보고 이 부분이 살짝 헷갈렸는데, 그냥 처음 생각으로는 2번의 인덱스(제목 3부분)과 3번의 인덱스(제목 4부분)가 사라져야하는게 아닌가 싶었다.

하지만 코드가 순차 진행되면서 2번 인덱스의 내용이 먼저 지워졌으니 자동적으로 3번이 2번으로, 4번이 3번으로 움직였기에 다음 3번 인덱스가 지워져야 할때는 제목5부분이 그 안에 자리잡고 있었던 것.

실행 결과


LinkedList

  • 사용 방법은 ArrayList와 동일

  • ArrayList는 내부 배열에 객체를 저장해서 인덱스로 관리하지만,
    LinkedList는 말그대로 링크를 인접 참조해서 체인처럼 관리한다.

  • 중간 삽입, 중간 삭제에 있어 ArrayList보다 좋은 성능을 발휘한다.

ArrayList는 뒤쪽 인덱스들을 모두 1씩 증가 또는 감소시키는 시간이 필요하지만
LinkedList는 앞 뒤 링크정보만 변경하면 되기 때문에
ArrayList < LinkedList

속도 차이 확인하기

먼저 인덱스 0번에 내용을 계속 추가해준다.

List<String> list1 = new ArrayList<String>();
List<String> list2 = new LinkedList<String>();
		
long startTime;
long endTime;
		
// 0번 인덱스부터 넣어주기
System.out.println("인덱스 0번에 계속 추가해주기");
// 현재 시간을 나노초 단위로 받아온다
startTime = System.nanoTime();
for(int i=0; i<100000; i++) {
	list1.add(0, String.valueOf(i));
}
endTime = System.nanoTime();
System.out.println("ArrayList  걸린시간 : " + (endTime - startTime) + " ns");
			
startTime = System.nanoTime();
for(int i=0; i<100000; i++) {
	list2.add(0, String.valueOf(i));
}
endTime = System.nanoTime();
System.out.println("LinkdeList 걸린시간 : " + (endTime - startTime) + " ns");
		
System.out.println();
		
// 마지막 부분에만 새로운 값 계속 붙여주기
System.out.println("마지막 부분에 값 추가해주기");
// 현재 시간을 나노초 단위로 받아온다
startTime = System.nanoTime();
for(int i=0; i<100000; i++) {
	list1.add(String.valueOf(i));
}
endTime = System.nanoTime();
System.out.println("ArrayList  걸린시간 : " + (endTime - startTime) + " ns");
		
		
startTime = System.nanoTime();
for(int i=0; i<100000; i++) {
	list2.add(String.valueOf(i));
}
endTime = System.nanoTime();
System.out.println("LinkdeList 걸린시간 : " + (endTime - startTime) + " ns");

실행 모습

단순 계산이라 극적인 차이는 나지 않는 것 같지만, 실행 내용이 복잡해 질수록 그 차이는 더 커질것이라고 생각된다.

0개의 댓글