코딩 화이팅 2023. 1. 27. 14:54
  • 객체들을 한 곳에 모아두고 편리하게 사용할 수 있는 환경을 제공

정적 자료구조

  • 배열이 대표적인 정적 자료구조
  • 고정된 크기의 자료구조

동적 자료구조

  • 요소의 개수에 따라 자료구조의 크기가 동적으로 증가하거나 감소
  • ex) 리스트 스택 큐 등

Collection Interface

package test01_list;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

public class test01 {
	public static void main(String[] args) {
		// List
		// 순서(index)가 있는 자료구조 / 중복 허용
//		List<String> names = new ArrayList<>();
//		List<String> names = new LinkedList<>();
		List<String> names = new Vector<>();

		// 원소 추가
		names.add("안중근");
		names.add("이봉창");
		names.add("이순신");
		names.add(0, "이순신");// 0번 인덱스에다가 선언

		System.out.println(names);

		// 비었는지 확인
		System.out.println(names.isEmpty());

		// 원소의 갯수
		System.out.println(names.size());

		// 인덱스 수정
		names.set(2, "세종대왕");
		System.out.println(names);

		// 조회
		for (String name : names) {
			System.out.println(names);
		}
		// 반복자 사용
		Iterator<String> e = names.iterator();
		while (e.hasNext()) {//다음 원소가 있다면
			System.out.println(e.next());//그 다음 원소를 출력한다.
		}

		// 삭제
		names.remove(2);
		System.out.println(names);

		// 값 삭제
		names.remove("이순신");
		System.out.println(names);

		// 전부 삭제
		names.clear();
		System.out.println(names);

		names.add("강현");
		names.add("강현");
		names.add("현강");
		for (int i = 0; i < names.size(); i++) {
			System.out.println(names.get(i));//get-특정 인덱스에 있는것을 가져온다
		}

		// 강현 삭제하고싶다
//		for (int i = 0; i < names.size(); i++) {//크기가 동적으로 변하므로 names.size가 변한다. 따라서 한개의 강현밖에 안 사라짐
//			if (names.get(i).equals("강현")) {
//				names.remove(i);
//			}
//		}
		for (int i = names.size() - 1; i >= 0; i--) {// 뒤에서부터 지우면 강현을 다 지울 수 있다. / 때로 뒤에서부터 수행해야 할 때가 있다.
			if (names.get(i).equals("강현")) {
				names.remove(i);
			}
			System.out.println(names);
		}
	}
}
//ArrayList, LinkedList, Vector 성능 비교
//추가, 수정, 조회

package test01_list;


import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

public class test02 {
	public static void main(String[] args) {
		List<Object> al= new ArrayList<Object>();
		List<Object> ll= new LinkedList<Object>();
		List<Object> v = new Vector<Object>();
		
		test1("순차적 추가 -  ArrayList -", al);
		test1("순차적 추가 - LinkedList -", ll);
		test1("순차적 추가 -   Vector   -", v);
		
		test2("중간에 추가 -  ArrayList -", al);
		test2("중간에 추가 - LinkedList -", ll);
		test2("중간에 추가 -   Vector   -", v);
		
		test3("데이터 조회 -  ArrayList -", al);
		test3("데이터 조회 - LinkedList -", ll);
		test3("데이터 조회 -   Vector   -", v);
	}
	
	public static void test1(String testname, List<Object> list) {
		long start=System.nanoTime(); //시작 시간
		for (int i = 0; i < 50000; i++) {
			list.add(new String("Hello"));//뒤에다가 추가
		}
		long end=System.nanoTime(); // 끝 시간
		System.out.printf("%s \t 소요시간:%15d ns. \n", testname, end-start);
	}
	
	public static void test2(String testname, List<Object> list) {
		long start=System.nanoTime(); //시작 시간
		for (int i = 0; i < 50000; i++) {
			list.add(0, new String("Hello")); //맨 앞에다가 추가(중간에 추가)
		}
		long end=System.nanoTime(); // 끝 시간
		System.out.printf("%s \t 소요시간:%15d ns. \n", testname, end-start);
	}
	
	public static void test3(String testname, List<Object> list) {
		long start=System.nanoTime(); //시작 시간
		//리스트에 있는 모든 원소 조회
		for (int i = 0; i < list.size(); i++) {
			list.get(i);
		}
		long end=System.nanoTime(); // 끝 시간
		System.out.printf("%s \t 소요시간:%15d ns. \n", testname, end-start);
	}
}
/*
순차적 추가 -  ArrayList - 	 소요시간:        3520200 ns. 
순차적 추가 - LinkedList - 	 소요시간:        1914000 ns.
순차적 추가 -   Vector   - 	 소요시간:        1787000 ns. 
중간에 추가 -  ArrayList - 	 소요시간:      590436100 ns. 
중간에 추가 - LinkedList - 	 소요시간:        2414300 ns. 
중간에 추가 -   Vector   - 	 소요시간:      595096300 ns. 
데이터 조회 -  ArrayList - 	 소요시간:        3247300 ns. 
데이터 조회 - LinkedList - 	 소요시간:     4176980200 ns. 
데이터 조회 -   Vector   - 	 소요시간:        4165700 ns. 
*/

List

  • 순서가 있고, 중복을 허용(배열과 유사)
  • 구현 클래스 : ArrayList / LinkedList / Vector
  • 내부적으로 배열을 이용하여 데이터를 관리(ArrayList, Vector)
  • 배열과 다르게 크기가 유동적으로 변함(동적 자료구조)

ArrayList

  • 장점 : 가장 기본적인 형태의 자료구조, 간단하며 사용이 쉬움 / 접근 속도가 빠름 / 조회할 때 빠름
  • 단점 :  크기를 변경할 수 없어 데이터를 위해 새로운 배열을 만들고 복사해야함. / 비 순차적 데이터의 추가, 삭제에 많은 시간이 걸림 / 추가와 삭제에 불리하다.

LinkedList

  • 각 요소를 Node로 정의하고 Node는 다음 요소의 참조 값과 데이터로 구성됨
  • 각 요소가 다음 요소의 링크 정보를 가지며 연속적으로 구성될 필요가 없음
  • 장점 : 추가 삭제에서 유리
  • 단점 : 조회에서 불리
package test02_set;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

public class test01 {
	public static void main(String[] args) {
		//set
		//집합을 나타내는 자료구조
		//중복을 허용X
		//순서도 없음
		Set<String> set = new HashSet<>();//해쉬 테이블에 원소를 저장 / 성능면에서 우수 / 원소들의 순서가 일정하지 않다
//		Set<String> set = new TreeSet<>();//red-black tree에 원소 저장 / 값에 따라서 순서가 결정 / 값을 순서대로 정렬할 필요가 있다면 고려해볼만한 선택지
		
		set.add("강현");
		set.add("강현");
		set.add("강현일");
		set.add("강현이");
		
		System.out.println(set);
		
		System.out.println("강현".hashCode());//고유한 정수값으로 나타낸 것
		System.out.println("강".hashCode());
		System.out.println(new String("강현").hashCode());//같은 문자열이면 같은 해쉬코드가 나온다.
		
		System.out.println("강현".equals("강현"));//해시코드가 같다면 equals 메소드에 참 출력
		
	
	//반복자
		Iterator<String> e=set.iterator();
		while (e.hasNext()) {
			System.out.println(e.next());
		
		}
	}
}
//HashSet일 때
[강현이, 강현, 강현일]
1420431
44053
1420431
true
강현이
강현
강현일
//TreeSet일 때
[강현, 강현이, 강현일]
1420431
44053
1420431
true
강현
강현이
강현일
package test02_set;

import java.util.HashSet;
import java.util.Set;

public class test02 {
	public static void main(String[] args) {
		Set<person> set=new HashSet<>();//hashcode, equals 두개가 같아야 같은 걸로 봄
		
		person p1=new person("강현", "980821");
		person p2=new person("강현", "980821");
		
		set.add(p1);
		set.add(p2);
		
		System.out.println(p1.hashCode());
		System.out.println(p2.hashCode());
		
		System.out.println(p1.equals(p2));
		
		System.out.println(set);
	}
}
===============================================================
package test02_set;

public class person {
	private String name;
	private String id;
	
	public person(String name, String id) {
		super();
		this.name = name;
		this.id = id;
			
	}
	
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return this.id.hashCode();//해시코드를 리턴한다.
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof person) {//만약 obj가 person 클래스의 객체라면
			person other=(person) obj; //other라는 변수에 obj를 person클래스로 형변환해서 선언
			return this.id.equals(other.id);//id만 같다면 equals해라
		}
		else {
			return false; 
		}
	}


	@Override
	public String toString() {
		return "person [name=" + name + ", id=" + id + "]";
	}
}

Set

  • 순서가 없고, 중복을 허용하지 않음
  • 장점 : 빠른 속도, 효율적인 중복 데이터 제거 수단
  • 단점 : 단순 집합의 개념으로 정렬하려면 별도의 처리가 필요하다.
  • 구현 클래스 : HashSet / TreeSet
package test03_map;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class test01 {
	public static void main(String[] args) {
		//map
		//사전과 같은 자료구조
		//키&값 쌍으로 저장
		//키로 구별
		//키는 중복X
		//값은 중복 가능
		Map<String, String> map=new HashMap<>();
//		Map<String, String> map=new TreeMap<>();
		
		//맵에 값 저장
		map.put("강", "010-1234-1234");
		map.put("현", "010-1111-1111");
		map.put("강현", "010-2222-2222");
		
		//중복된 키로 값을 넣을 경우 새로운 값으로 대체
		map.put("강현", "010-3333-3333");
		
		System.out.println(map);
		
		//값을 가져오는 것
		System.out.println(map.get("강"));
		
		//없는 키로 값을 가져온다면
		System.out.println(map.get("현강"));
		
		//키가 있는지 미리 확인
		System.out.println(map.containsKey("현강"));
		
		//값이 있는지 확인
		System.out.println(map.containsValue("010-3333-3333"));
		
		//반복문
		for(Map.Entry<String, String> entry : map.entrySet()) {
			System.out.println(entry.getKey()+" : "+entry.getValue());
		}
		//
        현 : 010-1111-1111
	강 : 010-1234-1234
	강현 : 010-3333-3333
        
		Iterator<String> e=map.keySet().iterator();
		while (e.hasNext()) {
			String key=e.next();
			System.out.printf("키: %s, 값: %s \n", key, map.get(key));	
		}
		for(String key:map.keySet()) {
			System.out.printf("키: %s, 값: %s \n", key, map.get(key));
		}
        //
        키: 현, 값: 010-1111-1111 
	키: 강, 값: 010-1234-1234 
	키: 강현, 값: 010-3333-3333 
	키: 현, 값: 010-1111-1111 
	키: 강, 값: 010-1234-1234 
	키: 강현, 값: 010-3333-3333
		
		System.out.println(map.size());//키의 갯수
	}
}

Map

  • Key와 value를 하나의 Entry로 묶어서 데이터 관리, 순서는 없으며, 키에 대한 중복은 없음
  • 장점 : 빠른 속도
  • 구현 클래스 : HashMap, TreeMap

Queue(큐)

  • 인터페이스, 구현체는 LinkedList를 사용
  • 큐 자료구조 : FIFO, 가장 먼저 들어온거부터 빠져나감

Stack

  • 스택 클래스를 사용
  • 스택 자료구조 : LIFO, 가장 나중에 들어온 값이 가장 먼저 빠져나감
package test06_sort;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class test01 {
	public static void main(String[] args) {
		String[] arr= {"samsung", "sofyware", "academy", "for", "youth"};
		List<String> list=Arrays.asList(arr);
		System.out.println(list);
        //[samsung, sofyware, academy, for, youth]
        
		//cf.Arrays.sort
		//collection을 정렬할 때는
		//collection.sort()
		Collections.sort(list);
		System.out.println(list);
        //[academy, for, samsung, sofyware, youth]
	}
}

정렬

  • 요소를 기준에 대한 내림차순 또는 오름차순으로 배치하는 것
  • 순서를 가지는 Collection들만 정렬 가능
    List 계열
    Set에서는 SortedSet의 자식 객체
    Map에서는 SortedMap의 자식 객체(Key 기준)
  • Collection의 sort()를 이용한 정렬
    객체가 Comparable을 구현하고 있는 경우 내장 알고리즘을 통해 정렬

Comparable interface

package test07_comparable;

//Collections.sort를 사용하고 싶으면 해당 클래스가 comparable 인터페이스를 구현해야한다.

public class person implements Comparable<person>{
	private String name;
	private String id;
	
	public person(String name, String id) {
		super();
		this.name = name;
		this.id = id;
			
	}
	
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return this.id.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof person) {
			person other=(person) obj;
			return this.id.equals(other.id);
		}
		else {
			return false;
		}
	}


	@Override
	public String toString() {
		return "person [name=" + name + ", id=" + id + "]";
	}

	
	//compareTo
	//양수 : 자리를 바꿈
	//음수 : 그대로
	//0 : 그대로
	
	@Override
	public int compareTo(person o) {
		//이름 순으로 정렬(String의 메서드를 이용)
//		return this.name.compareTo(o.name);
		//나이 순으로
		return Integer.parseInt(o.id)-Integer.parseInt(this.id);
	}
	
}
==============================================================
package test07_comparable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class test01 {
	public static void main(String[] args) {
		List<person> list=new ArrayList<person>();
		
		list.add(new person("강","980822"));
		list.add(new person("현","990823"));
		list.add(new person("현강","970824"));
		
		Collections.sort(list);
		System.out.println(list);
	}
}
//
[person [name=현, id=990823], person [name=강, id=980822], person [name=현강, id=970824]]

Comparator Interface

package test08_comparator;

import java.util.Comparator;

public class ageComparator implements Comparator<person>{

	@Override
	public int compare(person o1, person o2) {
		return Integer.parseInt(o1.getId())-Integer.parseInt(o2.getId());
	}

}
==============================================================
	package test08_comparator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class test01 {
	public static void main(String[] args) {
		List<person> list=new ArrayList<person>();
		
		list.add(new person("강","990822"));
		list.add(new person("현","908823"));
		list.add(new person("현강","980824"));
		
		Collections.sort(list, new ageComparator());
		System.out.println(list);
	}
}