본문 바로가기

Java/공부

[Java] 컬렉션 (Collection) _ List, Set, Map 0316

컬렉션

1) 정의

- 자바에서 제공하는 자료구조를 담당하는 프레임워크

- 추가, 삭제, 정렬 등의 기능을 간단히 해결해줌

- java.util 패키지에 포함됨

 

2) 배열과 컬렉션의 비교

배열 컬렉션
한 번 크기를 지정하면 변경 불가 크기의 제약이 없음
추가, 삭제, 정렬 어려움 추가, 삭제, 정렬 쉬움
한 타입의 데이터만 저장 가능 여러 타입의 데이터 저장 가능

 

3) 종류

- List

- Set

- Map

 

List

1) 정의

- 자료들을 순차적으로 나열한 자료구조

- 객체배열과 유사

 

2) 특징

-  순서가 유지, 저장됨

- 인덱스로 관리

- 객체의 중복 저장 가능

 

3) List의 후손

ArrayList 초기 저장 용량은 10으로 설정
용량을 초과한 객체가 들어오면 길이가 자동으로 변화, 고정도 가능
검색, 조회에 효율적
동기화를 제공하지 않음
LinkedList 인접 참조를 링크해 체인처럼 관리
추가, 수정, 삭제에 효율적
Vector ArrayList와 동일하나 동기화를 제공, 성능이 떨어지는 편

 

4) Array List

- 작성법

List [변수명] = new ArrayList();
// 기본 생성자 사용시 길이 10짜리의 리스트가 생성됨

// 저장 타입을 제한하고 싶은 경우 *제네릭(Generics) 를 사용해 작성함
List< 타입 > [변수명] = new ArrayList< 타입 >();

 

- 주로 사용되는 메서드

   1. List.add(Object e) : 리스트에 객체를 추가

    * Object를 매개변수로 사용시 모든 객체를 매개변수로 전달할 수 있음

	/**
	 * 1. 학생 정보 추가 메서드
	 * - 추가 성공시 "성공" , 실패시 "실패" 문자열 반환
	 */
	public String addStudent() throws InputMismatchException {

		System.out.println("========== 학생 정보 추가 ==========");
		System.out.print("이름 : ");
		String name = sc.next();

		System.out.print("나이 : ");
		int age = sc.nextInt(); // InputMismatchException
		sc.nextLine(); // 입력 버퍼에 남은 개행문자 제거

		System.out.print("사는곳 : ");
		String region = sc.nextLine();

		System.out.print("성별 : ");
		char gender = sc.next().charAt(0); //String -> char

		System.out.print("점수 : ");
		int score = sc.nextInt(); // InputMismatchException

		// Student 객체 생성해 List에 추가
		if(studentList.add(new Student(name, age, region, gender, score))) {
			// List.add(Student e) 
            // -> 제네릭 <Student>때문에 리스트 타입이 제한됨
            
			// (반환형)
			// add()는 boolean타입을 반환하는 메서드로,
            // 무조건 true를 반환 == 무조건 "성공"을 반환!
			// 대신 예외가 발생해서 add() 수행 전 메서드가 종료될 수는 있으므로
            // throws InputMismatchException 를 이용해 예외처리를 할 것 !!!!
			return "성공";
		}else {
			return "실패";

		}

	}

 

    2. List.size() : 리스트의 길이를 확인

    3. Object List.get(index i) : 리스트에서 i번째 인덱스에 있는 객체를 반환

/** 2. 학생 전체 조회 메서드 */
	public void selectAll() {
		
		System.out.println("========== 학생 전체 조회 =========");
		
		// * studentList가 비었는지 확인하는 방법
		// 1) studentList.size()==0 -> List의 개수 확인
		// 2) studentList.isEmpty() -> (boolean) 비어있으면 true출력
        
		if(studentList.size()==0) { 
			System.out.println("학생 정보가 없습니다.");
			return; 
			// 현재 메서드를 종료하고, 호출한 곳으로 돌아감
			// 반환값이 없어도 됨 (void)
		}
        ----------------------------------------------------------------
        
        // * List의 인덱스를 이용해 저장된 개수를 얻어오기 [1] 
        // for문 사용
        // List.size()를 이용해 저장된 개수 확인 (배열명.length 대신 사용)
		
        for(int i = 0 ; i <studentList.size() ; i++) {
			System.out.println(studentList.get(i)); 
            //studentList에서 i번째 인덱스요소를 얻어와 출력
		}
        
        ----------------------------------------------------------------
		
		// * List의 인덱스를 이용해 저장된 개수를 얻어오기 [2]
        // 향상된 for문 (for each문) 사용
		//  - 컬렉션, 배열의 모든 요소를 순차적으로 반복 접근할 수 있는 for문
		//  - 0번 인덱스부터, 마지막 요소까지 인덱스를 1씩 증가한다
		//  [작성법]
		//  for( 컬렉션 또는 배열에서 꺼낸 한 개의 요소 저장할 변수 : 컬렉션명 혹은 배열명){}

		int index = 0;
		for( Student std : studentList){
			// std에for문 반복시마다 0,1,2,... 인덱스 요소들이 한번씩 저장됨
			System.out.print( (index++) + "번 : ");
			System.out.println( std );
		}
	}

 

   4. Object List.remove(int index) : List에서 index번째 요소를 제거

      이 때, 제거된 요소가 반환되고

      중간에 비어있는 index가 없게 하기 위해 동작시 뒤쪽 요소를 한칸씩 당겨온다

	/**
	 * 4. 학생 정보 제거 메서드
	 */
	public String removeStudent() throws InputMismatchException {
		
		System.out.println("========== 학생 정보 삭제 ==========");
		
		System.out.print("인덱스 번호 입력 : ");
		int index = sc.nextInt();
		sc.nextLine();
		
		// 1) 학생 정보가 studentList에 있는가 ?
		if(studentList.isEmpty()) {
			return "입력된 학생 정보가 없습니다.";
            
			// 2) 입력된 숫자가 0보다 큰가? (음수 검사)
		}else if(index<0) {
			return "음수는 입력할 수 없습니다.";
			
			// 3) 만약 문자열을 입력한 경우 -> throws 예외처리
			
			// 4) 입력받은 숫자가 studentList범위 내 인덱스 번호인가?
		}else if(index >= studentList.size()){
			return "범위를 넘어선 값을 입력할 수 없습니다.";
			
			// 5) 삭제 코드 작성
		}else {
			
			System.out.println("정말 삭제 하시겠습니까 ? (Y/N) ");
			char ch = sc.next().toUpperCase().charAt(0);
			// String -> 대문자 String -> 대문자 0번 인덱스 문자로 변환
			
			// * String.toUpperCase(); : 문자열을 대문자로 변경
			
			if(ch == 'Y') {
				Student temp = studentList.remove(index);
				return temp.getName() + "의 정보가 제거되었습니다. ";
			}else {
				return "취소";
			}
			
		}
		
	}

 

Set

1) 정의

- 저장 순서가 유지되지 않고, 중복 객체도 저장하지 못하게 하는 자료구조

 

2) 특징

- 순서 없음

- 중복저장 안됨 (null도 중복안됨)

 

3) Set의 후손

HastSet Set의 대표적인 자식 클래스
저장되는 객체의 equals(), hashCode() 오버라이딩 필수
LinkedHashSet 순서 유지 Set
TreeSet 자동 정렬 Set

* Hash라는 단어가 붙은 모든 컬렉션은 반드시 저장되는 객체에

  equals(). hasgCode() 메서드를 오버라이딩해야한다.

 

4) HastSet

- 작성법

	Set< 저장할 타입 > set = new HashSet< 저장할 타입 >();

----------------------------------------------------
	// equals() hashCode() 오버라이딩 자동완성 alt + shift + s

	@Override
	public int hashCode() {
		return Objects.hash(age, id, pw);
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Member other = (Member) obj;
		return age == other.age && Objects.equals(id, other.id) && Objects.equals(pw, other.pw);
	}

 

- 주로 사용되는 메서드

    1. Set.add( 저장할 타입 ) : Set에 객체를 추가

	Set<String> set = new HashSet<String>();

		// Set.add(String e)
		set.add("네이버");
		set.add("카카오");
		set.add("라인");
		set.add("쿠팡");
		set.add("배달의민족");
		set.add("배달의민족");
		set.add("배달의민족");
		set.add(null);
		set.add(null);
		set.add(null);
        
        System.out.println(set);
        // 출력시 [null, 배달의민족, 카카오, 네이버, 쿠팡, 라인] 출력됨
		// 순서x, 중복x, null 중복 x 확인 가능

 

    2. Set.size() : Set에 저장된 데이터의 개수 반환

    3. Set.remove(저장할 타입) : Set에 저장된 객체 중 매개변수와 필드값이 같은 객체를 제거

    만약 Hash라는 단어가 포함된 Set면 hashCode()도 동일해야 삭제가능

    지우면 true반환, 못지우면 false를 반환함

		Set<String> set = new HashSet<String>();
        
		set.add("네이버");
		set.add("카카오");
		set.add("라인");
		set.add("쿠팡");
		set.add("배달의민족");
		set.add("배달의민족");
		set.add("배달의민족");
		set.add(null);
		set.add(null);
		set.add(null);
		
		System.out.println(set);
		// [null, 배달의민족, 카카오, 네이버, 쿠팡, 라인] 출력됨
		
		System.out.println("저장된 데이터의 수 : "+set.size());
        // 6 출력
		
		System.out.println(set.remove("라인"));    // 지웠으면 true 반환
		System.out.println(set.remove("야놀자"));  // 못지웠으면 false 반환
		System.out.println(set); 
        // 출력시 remove된 내역 확인 [null, 배달의민족, 카카오, 네이버, 쿠팡]

 

    4. set.iterator() :  컬렉션에서 제공하는 컬렉션 객체 반복 접근자

       (컬렉션에 저장된 데이터를 임의로 하나씩 반복적으로 꺼내는 역할)

    5. it.hasNext() : 다음값이 있으면 true 반환
         it.next() : 다음 값(객체)를 얻어옴

Set<String> set = new HashSet<String>();

		set.add("네이버");
		set.add("카카오");
		set.add("쿠팡");
		set.add("배달의민족");
        set.add(null);
        
        Iterator<String> it = set.iterator();
        
        while(it.hasNext()) {
			// it.hasNext() : 다음값이 있으면 true 반환
			// it.next() : 다음 값(객체)를 얻어옴
			// 하나씩 꺼냈을 때 다음값이 없는 경우 == false 반복 종료
			
			String temp = it.next();
			
			System.out.print(temp + ",");
		}
        
        // null, 배달의민족, 카카오, 네이버, 쿠팡 출력함
        
        -----------------------------------------------
        // 향상된 for문을 사용해 간단히 출력할 수도 있다
        for( String temp : set ) {
			System.out.println(temp);
		}

 

    6. equals() : 원래는 문자열의 값이 같은지 비교하는 메서드인데, 

       현재 객체와 매개변수로 전달받은 객체의 필드가 같은지 비교하는 형태로 오버라이딩해야함.

       hashCode() : 중복제거를 위해 객체의 필드값을 이용해 특정 정수를 반환해주는 메서드,

       필드 값이 같은 객체는 같은 정수를 반환할 수 있도록함. 

		// 중복 제거를 위해!!!!
		// set 사용시 equals() 오버라이딩 필수!
		// hash- 사용시 hashCode() 오버라이딩 필수!
	
	public void ex3() {
		// equals()만 오버라이딩 된 Member를 set에 저장
		// [key point] 중복 제거가 되는가?
		
		Set<Member> memberSet = new HashSet<Member>();
		
		memberSet.add( new Member("user01", "pass01", 30));
		memberSet.add( new Member("user02", "pass02", 40));
		memberSet.add( new Member("user03", "pass03", 20));
		memberSet.add( new Member("user04", "pass04", 25));
		memberSet.add( new Member("user04", "pass04", 25));
		
		for(Member mem : memberSet) {
			System.out.println(mem); // 중복제거 되지 않음
		}
		
		// - equals()가 오버라이딩 되어있지만 중복 제거가 되지 않음
		// - 중복 제거를 위해 hashSet은 hashCode()도 오버라이딩 해야한다
        
        // hashCode() 오버라이딩 후
		
		Member mem1 = new Member("user01", "pass01", 30);
		Member mem2 = new Member("user01", "pass01", 30);
		Member mem3 = new Member("user01", "pass01", 31);
		
		System.out.println(mem1.hashCode());
		System.out.println(mem2.hashCode()); 
		System.out.println(mem3.hashCode()); 
        // 필드값이 동일하기때문에, mem1과 mem2는 같은 해쉬코드 출력
        // mem3은 다른 해쉬코드를 출력한다.
        
        // hashCode() 오버라이딩 후 위에서 실행했던,
        // for문을 재실행해보면 중복이 제거된 내역을 확인 할 수 있다.
		
	}

 

  7. Wrapper 클래스 : 기본 자료형을 객체로 포장하는 클래스

     컬렉션에 기본 자료형 값을 저장할 때 사용,

     기본 자료형에 없던 추가 기능 혹은 값을 이용하고 싶을 때 사용함

     (Wrapper 클래스 종류 : Integer, double, Boolean, Byte, Short, Long, Float, Character)

 

		int iNum = 10;      // -> Integer
		double dNum = 3.14; // -> Double

		// 기본자료형 -> 포장
		Integer w1 = new Integer(iNum); // int가 Integer로 포장됨
		Double w2 = new Double(dNum); // double이 Double로 포장됨
		
		// Wrapper 클래스 활용
		System.out.println("int 최대값 : " + w1.MAX_VALUE);
		System.out.println("double 최소값 : " + w2.MIN_VALUE);
					// 기울어진 글씨 : static !
					// static 은 객체를 생성하지 않고도, 
					// 클래스명.필드명, 클래스명.메소드명() 호출 가능
		
		System.out.println("int 최소값 : " + Integer.MIN_VALUE);
		System.out.println("double 최대값 : " + Double.MAX_VALUE);
		
		//************************************************************
		// 데이터 파싱 (parsing) 데이터의 형식을 변환하는것
		
		// String데이터를 기본자료형으로 변환!
		
		// 1) 문자열 100을 int형식으로 변환하기
		int num1 = Integer.parseInt("100");
		System.out.println(num1); // 100 출력됨
		
		// 2) 문자열 1.23445를 double형식으로 변환하기
		double num2 = Double.parseDouble("1.23445");
		System.out.println(num2); // 1.23445 출력됨
		
		// 3) 정상적으로 변환되었는지 확인하기
		// 아직 문자열이면 이어쓰기 출력
		// 각각 정수-실수형으로 변경되었으면 연산된 값이 출력됨
		System.out.println(num1+num2); // 101.23445 출력됨

 

 + Wrapper 클래스의 AutoBoxing / AutoUnboxing

		Integer w1 = new Integer(100);
		// Integer에 삭제선 발생 (deprecated)
        // == 해당 구문은 삭제될 예정이다 (사용을 권장하지 않는다)
		
		Integer w2 = 100;
		Integer w3 = 100;
		// w2는 Integer형 참조형 변수 / 100은 int형 정수로
		// 자료형이 다른 w2와 100사이에 연산이 안되어야 하지만
		// Integer는 int의 포장된 형식이라는 것을 Java가 인식하고 있어서
		// 위와 같은 경우 int를 Integer로 자동포장 해준다. (AutoBoxing)
		
		System.out.println("w2+w3="+ (w2+w3));
		// w2 (Integer 객체)
		// w3 (Integer 객체)
		// w2 + w3 출력시 객체 + 객체 끼리의 연산으로
        // 덧셈이 아닌 이어쓰기가 출력돼야 하지만
		// Java는 Integer는 int의 포장형태 라는것을 인식하고 있음
		// + 연산시 포장을 자동으로 벗겨냄 (AutoUnboxing)
		// Integer + Integer -> int + int

 

ex ) Set을 이용해 간단히 로또 번호 생성하기 + ( LinkedHashSet / TreeSet 응용 )

	public void lotto() { 
		
		Set<Integer> lotto = new HashSet<Integer>();
		// Integer는 equals, hashCode() 오버라이딩 완료상태
		
		while(lotto.size()<6) { 
			// 중복 발생시 6개의 수가 저장되지 않으므로,
            // 빈공간이 생기지 않도록 while문을 사용해
			// lotto에 저장된 값이 6개 미만이면 반복
			
			int random = (int)(Math.random()*45+1);
			// 1 - 45 사이 난수 생성
			
			System.out.println("random =" +random);
			
			lotto.add(random);
			// int값이 자동으로 Integer에 포장되어 lotto에 추가 (AutoBoxing)
		}
		
		System.out.println("로또번호 : "+ lotto);
		
	}
    
   //  ---------------------------------------------------------------
   // 이 때, 
   // Set<Integer> lotto = new LinkedHashSet<Integer>(); 
   // LinkedHashSet 을 사용하면 순서가 유지되는 Set 를 생성할 수 있고,
   
   // Set<Integer> lotto = new TreeSet<Integer>(); 
   // TreeSet을 사용하면 자동 정렬이 되어있는 Set 을 생성할 수 있다.

 

Map

1) 정의

- 키 와 값의 쌍으로 구성된 자료구조

 

2) 특징

- 키는 중복 저장을 허용하지 않음 ( Set 방식 )

- 값은 중복 저장을 허용함 (List 방식)

 

3) Map의 후손

HashMap< K, V > Map의 자식 클래스 중 가장 대표되는 Map

 

4) HastMap< K, V >

- 작성법

Map< ket 타입 , value 타입> [변수명] = new HashMap< key타입 , Value타입 > ();

 

- 자주 사용되는 메서드

    1. Map.put :  Map에 객체를 추가

		Map<Integer, String> map = new HashMap<Integer, String>();
		
		// Map.put(integer Key, String Value) : 값 추가
		map.put(1,"홍길동");
		map.put(2,"고길동");
		map.put(3,"김길동");
		map.put(4,"박길동");
		map.put(5,"이길동");
		map.put(6,"최길동");
		
		// key 중복 -> 비허용; 새로 입력한 값 덮어쓰기
		map.put(1,"홍홍홍"); // 1, 홍길동이 1, 홍홍홍으로 덮어쓰기됨
		
		// value 중복 -> 허용; 
		map.put(7,"최길동"); // 7, 최길동이 map에 추가된다
		
		System.out.println(map);  
        // map.toString() 호출됨
        // {1=홍홍홍, 2=고길동, 3=김길동, 4=박길동, 5=이길동, 6=최길동, 7=최길동} 출력

 

    2. Map.get(Object key) : Map을 이용해 Object key의 값 가져오기 (일회성 VO 생성)

		// VO (값 저장용 객체)는 특정 데이터 묶음의 재사용이 많은 경우 사용
		// -> 재사용이 적은 VO는 코드 낭비 . . .
		// -> Map을 이용해 VO와 비슷한 코드를 작성할 수 있다.
        
        //------------------------------------------------------
		
		// 1) VO 버전
		Member mem = new Member();
		
		// 값 세팅
		mem.setId("user01");
		mem.setPw("pass01");
		mem.setAge(30);
		
		// 값 출력
		System.out.println(mem.getId()); // user01 출력
		System.out.println(mem.getPw()); // pass01 출력
		System.out.println(mem.getAge()); // 30 출력
        
        //------------------------------------------------------
		
		// 2) Map 버전
		Map<String, Object> map = new HashMap<String, Object>();
		
		// 값 세팅
		map.put("id", "user02");
		map.put("pw", "pass02");
		map.put("age", 25); // int -> Integer AutoBoxing (Object의 자손객체)
		
		// 값 출력
		System.out.println(map.get("id").toString());
		System.out.println(map.get("pw"));
		System.out.println(map.get("age"));
		// 실행전 : Object의 toString() 실행 == 정적바인딩
		// 실행후 : Member의 toString() 실행 == 동적바인딩 (자식 toString() 호출)

   

    3.  keySet() : Map의 key만 모아서 Set으로 반환

		// Map에 저장된 데이터 순차적으로 접근하기
        
		// Map에서 Key만 모아두면 Set의 특징을 가짐 
        // => keySet()메서드를 통해 key만 모아서 Set으로 반환
		
		Set<String> set = map.keySet();
		
		System.out.println(set); // [pw, id, age] 출력
		
		for(String key :set) {
			System.out.println(map.get(key));
			// key가 반복될 때 마다 변경된 key에 맞는 map의 value출력
            // (pass02, user02, 25)
			// 순서는 저장되지 않기 때문에 뒤죽박죽으로 나옴... 
		}
		
		// Map에 저장된 데이터가 많거나,
		// 어떤 key가 있는지 불분명하거나, 
		// 또는 Map에 저장된 모든 데이터에 접근해야 할 때 
		// keySet() + 향상된 for문 코드를 사용한다.

 

    4. List와 Map의 활용 ( List안에 Map 중첩하기)

		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        // List안에 Map을 중첩하여 list 생성
		
		for(int i = 0; i <10 ; i ++) {
			Map<String, Object> map = new HashMap<String, Object>();
			
			map.put("id", "user0"+i); // id, user01.. user02.. 대입
			map.put("pw", "pass0"+i); // pw, pass01.. pass02.. 대입
			
			// 만들어진 Map을 리스트에 추가
			list.add(map);
		}
		
		// for문 종료시 Lis에는 10개의 Map객체가 추가되었다.
		// 향상된 for문을 이용해
        // List에 저장된 Map에서 key가 "id"인 경우의 value를 모두 출력

		for(Map<String, Object> temp: list) {
			System.out.println(temp.get("id"));
            // pw만 출력하고 싶으면 temp.get("pw")를 출력하면 된다.
		}

'Java > 공부' 카테고리의 다른 글

[SERVLET / JSP] 간단 정리  (0) 2022.06.03
[JDBC] 정리  (0) 2022.04.03
[Java] 바인딩 (Binding) 0315_1  (0) 2022.03.21
[Java] 다형성 (Polymorphism)  (0) 2022.03.21
[Java] 상속 (Inheritance)  (0) 2022.03.21