IT/java

Java에서의 Array, List, Map, Set, lterator

토희 2022. 7. 4. 23:40
728x90

 

List는 왜 만들어졌냐?

=> 배열의 한계 때문, 배열을 사용하기 위해서는 크기를 정해야함!! 따라서 List 만들어짐

int[] num = new int[10]; // 크기 지정해야함 
List<Integer> num1 = new ArrayList<Integer>(); // 크기 지정 안해줘도 됨

 

 

ArrayList

데이터(객체) 저장공간으로 배열을 사용. 

ArrayList list1 = new ArrayList(10);
// ArrayList에는 객체만 저장가능
// autoboxing에 의해 기형이 참조형으로 자동 변환됨! 그리고 그냥 5 이렇게 적어도 된다
list1.add(5);
list1.add(new Integer(3));
list1.add(new Integer(4));
list1.add(new Integer(0));
list1.add(new Integer(1));

 

내부 인덱스를 이용, 검색 유리(빠른 검색 속도), but 데이터 추가 삭제시 많은 데이터가 밀리거나 당겨지기 때문에 많은 시간 소요


이를 보완하기 위해 Hash 등장 , 내부적으로 배열 사용,데이터 저장하기에 빠른 검색 속도, 데이터 추가 삭제시 기존 데이터 밀러거나 당겨지지 X, 특별한 알고리즘으로 데이터와 연관된 고유한 숫자를 만들어 낸 뒤 인덱스 사용

 

< 선언 >

// ArrayList 선언 
List<String> list = new ArrayList<String>();

< 메소드 >

1) add()

// add(값) : 리스트에 값 추가
list.add("ABC");
list.add("DEF");
// add(인덱스번호, 값) : 인텍스번호 위치에 값 추가, 기존값은 뒤로 밀림!
list.add(1, "GHI");

2) size()

// ArrayList의 크기 확인
System.out.println(list.size()); // 3

3) get()

for (int i = 0; i < list.size(); i++) {
	// get(인텍스번호) : 인텍스번호의 값을 가져옴
	System.out.println(list.get(i));
}

4) set()

// set(인텍스번호, 값) : 인텍스번호 위치의 값을 주어진 값으로 변경
list.set(1, "가나다");

5) remove()

// remove(인덱스번호) : 인덱스번호위치의 값을 제거, 뒤의 내용은 당겨옴(빈 공간 용납x)
list.remove(2);

// ArrayList는 값을 지우고, 없는 값 가져오면 터져버림, 에러, 혹은 뒤에꺼 땡겨오거나 오류남, map은 안터짐, null
// System.out.println(list.get(2)); // 오류

6) isEmpty()

// isEmpty() :비어있으면 true, 아니면 false
System.out.println(list.isEmpty());

7) contains()

// contains(값) : 리스트에 주어진 값과 일치한 값이 있는 확인, 있으면 true, 없으면 false
System.out.println(list.contains("가나다"));

8) indexOf(), lastIndexOf()

// indexOf(값) : 주어진 값과 일치하는 값의 위치 반환
System.out.println(list.indexOf("가나다"));
// lastIndexOf(값) : 주어진 값과 일치하는 값의 위치를 뒤에서부터 반환
System.out.println(list.lastIndexOf("가나다"));

9) toString()

// toString() : 출력가능한 값을 문자열의 형태로 취득
System.out.println(list.toString());

10) toArray()

// toArray() : 리스트를 배열로 변환, 형변환이 필요함, (String[])부분 클래스캐스팅이라고 함
// 숫자 가능!
String[] temp = (String[]) list.toArray();

11) clear()

// clear() : 리스트를 비옴
list.clear();

12) sort(null)

List<Integer> num = new ArrayList<Integer>();

num.add(5);
num.add(3);
num.add(7);

// sort(null) : 오름차순 정렬
num.sort(null);
System.out.println(num);

 

 

Map

키와 값을 가짐, 순서 X, 키값 중복 X

 

HashMap

< 선언 >

Map<Integer, String> map = new HashMap<Integer, String>();

< 메소드 >

1) put()

// put(값1, 값2) : 값1인 키에 값2를 넣는다
map.put(1, "가나다");
map.put(2, "라마바");
map.put(3, "사아자");

2. size()

// size() : 맵에 들어있는 개수를 돌려줌
System.out.println(map.size());

3. get()

// get(값) : 키 중에 값과 같은 것의 내용을 가져온다.
System.out.println(map.get(3));

4. replace()

// List의 set대신, replace(값1, 값2) : 값1과 일치하는 키에 값2를 할당
map.replace(2, "ABC");
System.out.println(map.get(2));

// map의 경우 put이 덮어씌우는 기능이 포함되어 있기 때문에 replace안쓰고 put을 씀
map.put(2, "DEF");
System.out.println(map.get(2));
System.out.println(map);

5. remove()

// remove(값) : 주어진 값과 일치하는 키의 데이터를 지움
map.remove(1);
System.out.println(map.get(1)); // 없으면 null

6) isEmpty()

// isEmpty() : 비어있는지 확인
System.out.println(map.isEmpty());

7) containsKey(), containsValue()

// 인덱스 기반이 아니기 때문에 indexOf 가 없고
// contains에 대해 더 세분화
// containsKey(값) : 값과 일치하는 키가 있는지 확인
// containsValue(값) : 주어진 값과 일치하는 값이 맴에 존재하는지 확인
System.out.println(map.containsKey(0));
System.out.println(map.containsValue("사야지"));

8) clear()

// clear() : map의 내용을 비운다.
map.clear();

9) keySet()

// keySet() : map의 키들을 Set으로 변환
Set<Integer> keySet = map.keySet(); // 넣는거에 치중

 

 

Set

데이터(객체)를 중복해서 저장할 수 없음. 또한 저장된 객체(데이터)를 인덱스로 관리하지 않기 때문에 저장 순서가 보장되지 않음. 수학의 집합과 비슷,

Set은 인덱스로 객체를 관리하지 않기 때문에 데이터를 검색하기 위해서는 iterator() 메서드로 Iterator(반복자)를 생성하고 데이터를 가져와야 함!

 

HashSet

< 선언 >

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

< 메소드 >

1. add()

set.add("one");
set.add("two");
set.add("three");
set.add("three");
set.add("two");
set.add("4");
set.add("5");
set.add("six");
// add()에서 중복값 넣어도 오류 안나지만, 출력하면은 데이터 1개씩만 출력됨

 

2. size()

// 데이터 수 출력 
System.out.println(set.size());

3. iterator()

// Iterator(반복자) 생성, 레코드판이라고 생각, 한번 만들어진 레코드판 수정 불가, 한번 적용되면 값이 변경불가
Iterator<String> it = set.iterator(); 

// 반복문이 횟수를 몰라서 while많이 씀
// Iterator의 hasNext() : Iterator의 데이터 중 현재 가르키는 위치에서 다음값이 존재하는지 확인
while (it.hasNext()) { // hasNext() : 데이터가 있으면 true 없으면 false
System.out.println(it.next()); // next() : 다음 데이터 리턴
}

3번까지의 메소드 실행후,

 

4. remove()

set.remove("three"); // 데이터 제거

// 다시 출력하기 위해서 
System.out.println("size는? " + set.size()); // 저장된 데이터 수 출력
// 반복자 재생성(위의 반복문에서 next 메서드로 데이터를 다 가져왔기 때문에 재생성을 해야함)
it = set.iterator(); 
while (it.hasNext()) {
	System.out.println(it.next());
}

 

6) isEmpty()

System.out.println(set.isEmpty());

7) contains()

System.out.println(set.contains("4"));
System.out.println(set.contains("three"));

8) clear()

set.clear();

 

lterator

Iterator(반복자)는 주로 데이터들을 묶는 List나 Map, Set과 같은 Collection에서 사용, next()를 통해 데이터들을 중복없이 하나씩 꺼낼 수 있도록 해준다. 참고로 List와 같이 저정된 데이터의 순서가 있는 경우를 제외하고는 데이터의 저장순서와 상관없이 무작위로 꺼냄

 

1. hasNext(), next()

// Iterator(반복자) 생성, 레코드판이라고 생각, 한번 만들어진 레코드판 수정 불가, 한번 적용되면 값이 변경불가
Iterator<String> it = set.iterator(); 

// 반복문이 횟수를 몰라서 while많이 씀
// Iterator의 hasNext() : Iterator의 데이터 중 현재 가르키는 위치에서 다음값이 존재하는지 확인
while (it.hasNext()) { // hasNext() : 데이터가 있으면 true 없으면 false
System.out.println(it.next()); // next() : 다음 데이터 리턴
}

2. remove()

String removeString = "six";
while(it.hasNext()){
   if(removeString.equals(it.next())){
     it.remove();
    }
}
System.out.println(set);
// Set이랑 연결

 

 

  크기제한 중복여부 순차적 용도
Array 고정 O O 추가, 수정, 삭제, 취득
List 무제한 O O 추가, 수정, 삭제, 취득
Map 무제한 키 값 중복 X X 추가, 수정, 삭제, 취득
Set 무제한 X X 추가, 수정, 삭제
Iterator 고정   O 삭제, 취득

 

각각의 메소드

  List Map Set Iterator
추가 add() put() add()  
수정 set() put()
replace()
   
삭제 remove()
clear()
remove()
clear()
remove()
clear()
remove()
취득 get() get()   hasNext(), next()

 

위에서 메소드는 List는 ArrayList, Map는 HashMap, Set는 HashSet 로 예를 들었지만,

인터페이스마다 각각 하나만 있는건 아님

LIst

1. ArrayList : ArrayList는 객체가 추가되어 용량을 초과하면 자동으로 부족한 크기만큼 용량이 늘어남

2. Vector :  ArrayList와 동일한 구조. 차이점이라면 Vector는 자동 동기화를 보장하므로 멀티 스레드 환경에서 안정적으로 사용이 가능. 하지만 단일 스레드에서는 ArrayList가 성능이 더 좋음

3. LinkedList : ArrayList, Vector는 덱스로 데이터를 관리하지만, LinkedList는 인접한 곳을 링크하여 체인처럼 관리. LinkedList는 중간의 데이터를 삭제할 때 인접한 곳의 링크만을 변경하면 되기 때문에 중간에 데이터를 추가/삭제하는 경우 처리 속도가 빠름

 

Map

1. HashMap :  key와 value를 묶어 하나의 entry로 저장, 해시 알고리즘(hash algorithm)을 사용하여 많은 양의 데이터를 검색하는데 검색 속도가 매우 빠름, 중복된 키로는 값을 저장할 수 없음. value에 null값도 사용 가능

Map의 가장 큰 특징은 순서에 의존하지 않고 key로 value를 가져오는데 있다. 하지만 가끔은 Map에 입력된 순서대로 데이터를 가져오고 싶은 경우도 있고 때로는 입력된 key에 의해 sort된 데이터를 가져오고 싶을 수도 있을 것이다. 이런 경우에는 LinkedHashMap과 TreeMap을 사용하는 것이 유리!

2. TreeMap :  입력된 key의 sort된 순으로 데이터가 출력됨

3. LinkedHashMap : 입력된 순서대로 데이터가 출력됨

 

Set

1. HashSet : 데이터를 중복 저장할 수 없고 순서를 보장하지 않음

2. TreeSet :  TreeSet도 HashSet과 같이 중복된 데이터를 저장할 수 없고 입력한 순서대로 값을 저장하지 않지만, TreeSet은 기본적으로 오름차순으로 데이터를 정렬

3. LinkedHashSet: LinkedHashSet도 중복된 데이터를 저장할 수 없음, 차이점은 입력된 순서대로 데이터를 관리

 

 

위의 메소드 테스트 한 전체 코드

ArrayList

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


public class ArrayListTest {

	public static void main(String[] args) {

		// ArrayList 선언 
		List<String> list = new ArrayList<String>();

		// add(값) : 리스트에 값 추가
		list.add("ABC");
		list.add("DEF");
		// add(인덱스번호, 값) : 인텍스번호 위치에 값 추가, 기존값은 뒤로 밀림!
		list.add(1, "GHI");

		System.out.println(list); // [ABC, GHI, DEF]
		// size() : 리스트의 개수를 가져옴
		System.out.println(list.size()); // 3

		for (int i = 0; i < list.size(); i++) {
			// get(인텍스번호) : 인텍스번호의 값을 가져옴
			System.out.println(list.get(i));
		}

		// 향상된 for문으로 가져오기, 대신 제네릭하고 타입 맞춰야함
		for (String s : list) {
			System.out.println(s);
		}

		// set(인텍스번호, 값) : 인텍스번호의 위치의 값을 주어진 값으로 변경
		list.set(1, "가나다");

		for (String s : list) {
			System.out.println(s);
		}

		// remove(인덱스번호) : 인덱스번호위치의 값을 제거, 뒤의 내용은 당겨옴(빈 공간 용납x)
		list.remove(2);

		// ArrayList는 없는 값 가져오면 터져버림, 에러, 혹은 뒤에꺼 땡겨오거나 지금은 오류남, map은 안터짐, null
		// System.out.println(list.get(2));

		for (String s : list) {
			System.out.println(s);
		}

		// isEmpty() :비어있으면 true, 아니면 false
		System.out.println(list.isEmpty());
		// contains(값) : 리스트에 주어진 값과 일치한 값이 있는 확인
		System.out.println("contains" + list.contains("가나다"));
		// indexOf(값) : 주어진 값과 일치하는 값의 위치를 지정
		System.out.println(list.indexOf("가나다"));
		// lastIndexOf(값) : 주어진 값과 일치하는 값의 위치를 뒤에서부터 지정
		System.out.println(list.lastIndexOf("가나다"));

		// sort(null) : 오름차순 정렬
		list.sort(null);
		// toString() : 출력가능한 값을 문자열의 형태로 취득
		System.out.println(list.toString());

		// toArray() : 리스트를 배열로 변환, 형변환이 필요함, (String[])부분 클래스캐스팅이라고 함
		// 숫자는 가능
		// String[] temp = (String[]) list.toArray();

		// clear() : 리스트를 비옴
		list.clear();
		System.out.println(list.isEmpty());

		System.out.println("======================================");

		List<Integer> num = new ArrayList<Integer>();

		num.add(5);
		num.add(3);
		num.add(7);

		// sort(null) : 오름차순 정렬
		num.sort(null);
		System.out.println(num);
		
	}
}

 

Map, Set, Iterator

package com.goodee.test.controller;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;


public class MapSet {

	public static void main(String[] args) {
		Map<Integer, String> map = new HashMap<Integer, String>();

		// put(값1, 값2) : 값1인 키에 값2를 넣는다
		map.put(1, "가나다");
		map.put(2, "라마바");
		map.put(3, "사아자");

		// get(값) : 키 중에 값과 같은 것의 내용을 가져온다.
		System.out.println(map.get(3));

		// size() : 맵에 들어있는 개수를 돌려줌
		System.out.println(map.size());
		// isEmpty() : 비어있는지 확인
		System.out.println(map.isEmpty());

		// 인덱스 기반이 아니기 때문에 indexOf 가 없고
		// contains에 대해 더 세분화
		// containsKey(값) : 값과 일치하는 키가 있는지 확인
		// containsValue(값) : 주어진 값과 일치하는 값이 맴에 존재하는지 확인
		System.out.println(map.containsKey(0));
		System.out.println(map.containsValue("사야지"));

		// remove(값) : 주어진 값과 일치하는 키의 데이터를 지움
		map.remove(1);
		System.out.println(map.get(1)); // 없으면 null

		// set없고, replace(값1, 값2) : 값1과 일치하는 키에 값2를 할당
		map.replace(2, "ABC");
		System.out.println(map.get(2));

		// map의 경우 put이 덮어씌우는 기능이 포함되어 있기 때문에 replace안쓰고 put을 씀
		map.put(2, "DEF");
		System.out.println(map.get(2));
		System.out.println(map);

		// clear() : map의 내용을 비운다.
		map.clear();
		System.out.println(map.isEmpty());

		map.put(1, "가나다");
		map.put(2, "라마바");
		map.put(3, "사아자");
		
		Set<String> set = new HashSet<String>();
		
		set.add("one");
		set.add("two");
		set.add("three");
		set.add("three");
		set.add("two");
		set.add("4");
		set.add("5");
		set.add("six");
		
		// 데이터 수 출력 
		System.out.println("size는? " + set.size());
		
		// Iterator(반복자) 생성, 레코드판이라고 생각, 한번 만들어진 레코드판 수정 불가, 한번 적용되면 값이 변경불가
		Iterator<String> it = set.iterator(); // Iterator(반복자) 생성

		// 반복문이 횟수를 몰라서 while많이 씀
		// Iterator의 hasNext() : Iterator의 데이터 중 현재 가르키는 위치에서 다음값이 존재하는지 확인
		while (it.hasNext()) { // hasNext() : 데이터가 있으면 true 없으면 false
			System.out.println(it.next()); // next() : 다음 데이터 리턴
		}
		
		set.remove("three"); // 데이터 제거
		System.out.println("size는? " + set.size()); // 저장된 데이터 수 출력
		it = set.iterator(); // 반복자 재생성(위의 반복문에서 next 메서드로 데이터를 다 가져왔기 때문에 재생성을
								// 해야함)
		String removeString = "six";
		 while(it.hasNext()){
             if(removeString.equals(it.next())){
                 it.remove();
             }
		}
		System.out.println(set);


		System.out.println(set.contains("4"));
		System.out.println(set.contains("three"));

		set.clear();
		System.out.println(set);
		
		System.out.println(set.isEmpty());
		
		Set<String> set1 = new HashSet<String>();
		
		set.add("one");
		set.add("two");
		set.add("three");
		set.add("three");
		set.add("two");
		set.add("4");
		set.add("5");
		set.add("six");
		
		Iterator<String> it1 = set.iterator(); 
		
		while (it1.hasNext()) { // hasNext() : 데이터가 있으면 true 없으면 false
			System.out.println(it1.next()); // next() : 다음 데이터 리턴
		}
	}
}

 

 

 

Set으로 랜덤숫자 구하기, 로또번호 구할때 써야지

public class RandomTest {

	public static void main(String[] args) {
		// 1 ~ 100사이의 중복되지 않는 정수 5개 만들기
		Set<Integer> intRnd = new HashSet<>();
		
		while(intRnd.size() < 5) { // Set의 데이터가 5개가 될 때까지..
			int num =(int) (Math.random() * 100+1);
			intRnd.add(num);
		}
		
		System.out.println(" 랜덤 숫자 : "+ intRnd);
		
		
       Set<Integer> intRnd1 = new TreeSet<>();
		
		while(intRnd1.size() < 5) { // Set의 데이터가 5개가 될 때까지..
			int num =(int) (Math.random() * 100+1);
			intRnd1.add(num);
		}
		
		System.out.println(" 랜덤 숫자 정 : "+ intRnd1);
	}

}

 

 

정리하고 나니 한 70퍼센트 이해한것 같음

내가 아직 잘 모르겠는 부분은

ArrayList 제네릭으로 선언

동기화

쓰레드

728x90