package ex0802;

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

/*
 - Map
 	: 키와 값 구조
 	: 키는 중복을 허용하지 않음
 	: 키는 순서가 없음
 	: 반복자가 없음(키는 반복자가 존재)
 - Map 구현 클래스
 	: HashMap - 동기화 지원하지 않음
 	: Hashtable - 동기화 지원
 	: TreeMap - 키 순서로 정렬. 키는 Comparable 인터페이스가 구현되어 있어야 함.
 */
public class Ex03_Map {
	public static void main(String[] args) {
		// 키, 값
		Map<String, Integer> map = new HashMap<String, Integer>();
		
		// map에 값 저장
		map.put("서울", 1000);
		map.put("부산", 350);
		map.put("대구", 250);
		map.put("인천", 350);
		map.put("광주", 150);
		map.put("대전", 150);
		map.put("울산", 110);
		map.put("세종", 20);
		map.put("서울", 980); // 동일한 키는 기존 값을 덮어씀
		System.out.println(map);
		
		// map에서 값 가져오기
		int n = map.get("서울");
		System.out.println(n);
		
		boolean b = map.containsKey("서울");
		System.out.println("키에 서울이 존재합니까 ? " + b);
		b = map.containsValue(350);
		System.out.println("값으로 350이 존재합니까 ? "+ b);
		
		System.out.println("map의 전체 데이터 개수 : " + map.size());
		
		map.remove("세종"); // 키가 세종인 데이터 삭제
		System.out.println(map);
		
		// Map은 Iterator가 존재하지 않음. 향상된 for 문도 사용 불가
		// 키는 처음부터 끝까지 순회가능(Iterator가 존재)
		Set<String> keySet = map.keySet(); // 키에서 Set 객체를 반환
		Iterator<String> it = keySet.iterator();
		while(it.hasNext()) {
			String key = it.next();
			Integer value = map.get(key);
			System.out.println(key + " -> " + value);
		}
		
	}
}

 

package ex0802;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Ex04_Map {

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

		map.put("자바", 80);
		map.put("오라클", 90);
		map.put("빅데이터", 100);
		map.put("서블릿", 60);
		map.put("스프링", 80);

		// map의 키를 Set으로 가져오기
		System.out.println("map의 키를 Set으로 가져오기");
		Set<String> set = map.keySet();
		System.out.println(set);

		System.out.println("map의 값을 List로 가져오기");
		List<Integer> list = new LinkedList<Integer>(map.values());
		System.out.println(list);

		System.out.println("\nmap 전체 리스트 -1");
		Iterator<String> it = map.keySet().iterator();
		while (it.hasNext()) {
			String key = it.next();
			int value = map.get(key);
			System.out.println(key + " -> " + value);
		}

		System.out.println("\nmap 전체 리스트 -2");
		for (String key : map.keySet()) {
			int value = map.get(key);
			System.out.println(key + " -> " + value);
		}
		
		
		
	}

}

package ex0802;

import java.util.Map;
import java.util.TreeMap;

public class Ex05_Map {

	public static void main(String[] args) {
		// TreeMap : 키로 정렬하여 저장. 키는 Comparable 인터페이스가 구현되어 있어야 함.
		// Comparable 인터페이스 : 정렬의 기준
		// Map<String, Integer> map = new TreeMap<>();
		TreeMap<String, Integer> map = new TreeMap<>();
		map.put("서울", 1000);
		map.put("부산", 350);
		map.put("대구", 250);
		map.put("인천", 350);
		map.put("광주", 150);
		map.put("대전", 150);
		map.put("울산", 110);
		map.put("세종", 20);
		
		System.out.println(map);
		
		Map<String, Integer> subMap = map.subMap("대전", "세종");
		System.out.println(subMap); // 대전에서 세종 전까지 추출
	}

}

 

'쌍용강북교육센터 > 8월' 카테고리의 다른 글

0805_Oracle : 단일행함수  (1) 2021.08.05
0803_Oracle : SQL  (1) 2021.08.04
0804_Oracle : SQL  (1) 2021.08.04
0802_Collections  (1) 2021.08.03
0802_Ex01~Ex02_Sort  (1) 2021.08.03

ArrayList

  • List 인터페이스 구현 클래스
  • 검색시 속도가 빠름
  • 동기화 되지 않음

Collections.sort(list); 정렬메소드는 Comparable을 구현한 클래스만 가능하다.

package ex0802;

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

public class Ex01_Sort {
	public static void main(String[] args) {
		List<UserVO> list = new ArrayList<UserVO>();
		list.add(new UserVO("너자바", "010-1111-1111", 23));
		list.add(new UserVO("홍길동", "010-2222-1111", 20));
		list.add(new UserVO("스프링", "010-1111-3333", 25));
		list.add(new UserVO("김자바", "010-1313-1111", 23));
		list.add(new UserVO("나나나", "010-1111-1515", 20));

		print("정렬 전...", list);

		// 정렬 : Comparable를 구현한 클래스만 가능 
		Collections.sort(list);
		print("정렬 후...", list);

	}

	public static void print(String title, List<UserVO> list) {
		System.out.println(title);
		for (UserVO vo : list) {
			System.out.print(vo.getName() + "\t");
			System.out.print(vo.getTel() + "\t");
			System.out.print(vo.getAge() + "\n");
		}
		System.out.println();
	}

}

class UserVO implements Comparable<UserVO> { // 정렬의 기준점을 만들어주어야 정렬할 수 있다.
	private String name;
	private String tel;
	private int age;

	public UserVO() {

	}

	public UserVO(String name, String tel, int age) {
		this.name = name;
		this.tel = tel;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	// compareTo : Comparable 인터페이스 메소드로 정렬할 때 정렬할 기준(방법)을 설정
	@Override
	public int compareTo(UserVO o) {
		// 이름 오름차순 : String capareTo() 메소드로 문자열을 비교
		// return name.compareTo(o.getName());
		
		// return -name.compareTo(o.getName()); // 이름 내림차순
		
		return age - o.getAge(); // 나이 오름 차순 
		
	}
}

 

package ex0802;

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

public class Ex02_Sort {
	public static void main(String[] args) {
		List<UserDTO> list = new ArrayList<UserDTO>();
		list.add(new UserDTO("나너노", "010-1111-2222", 25));
		list.add(new UserDTO("가나다", "010-3333-2222", 20));
		list.add(new UserDTO("호호호", "010-1111-4545", 23));
		list.add(new UserDTO("가도도", "010-1212-2222", 27));
		list.add(new UserDTO("마마마", "010-1111-5241", 23));
		
		print("정렬 전...", list);
		// Comparator 인터페이스 구현 : 정렬 기준 설정(이름 오름차순)
		Comparator<UserDTO> comp = new Comparator<UserDTO>() {
			@Override
			public int compare(UserDTO o1, UserDTO o2) {
				return o1.getName().compareTo(o2.getName());
			}
		};
		Collections.sort(list, comp);
		
		print("이름 오름차순...", list);
		
		// Comparator 인터페이스 구현 : 정렬 기준 설정(나이 오름차순)
		Comparator<UserDTO> comp2 = new Comparator<UserDTO>() {
			@Override
			public int compare(UserDTO o1, UserDTO o2) {
				return o1.getAge() - o2.getAge(); // 양수이면 swap
			}
		};
		Collections.sort(list, comp2);
			
		print("나이 오름차순...", list);

	}
	
	public static void print(String title, List<UserDTO> list) {
		System.out.println(title);
		for(UserDTO dto : list)	{
			System.out.print(dto.getName()+"\t");
			System.out.print(dto.getTel()+"\t");
			System.out.print(dto.getAge()+"\n");
		}
		System.out.println();
	}
}

class UserDTO {
	private String name;
	private String tel;
	private int age;

	public UserDTO() {
		
	}
	
	public UserDTO(String name, String tel, int age) {
		this.name = name;
		this.tel = tel;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

 

'쌍용강북교육센터 > 8월' 카테고리의 다른 글

0805_Oracle : 단일행함수  (1) 2021.08.05
0803_Oracle : SQL  (1) 2021.08.04
0804_Oracle : SQL  (1) 2021.08.04
0802_Collections  (1) 2021.08.03
0802_Ex03~Ex05_Map : 맵  (2) 2021.08.03
package ex0730;

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

/*
  ArrayList
    : List 인터페이스 구현 클래스
    : 검색시 속도가 빠름
    : 동기화 되지 않음(멀티 스레드에서 안전하지 않음)
  LinkedList
    : List 인터페이스 구현 클래스
    : 검색은 느림
    : 앞에서 추가하고 뒤에서 삭제가 빈번한 경우 빠름
    : 앞뒤 아무데서나 추가 삭제 가 빈번한 경우 
    : 중간에 삽입 삭제시에는 속도가 현저히 떨어짐. LinkedList 사용하지 말 것.
    : 동기화 되지 않음(멀티 스레드에서 안전하지 않음)
 */
public class Ex01_List {
	public static void main(String[] args) {
		List<String> list1 = new ArrayList<>();
		list1.add("자바");
		list1.add("오라클");
		list1.add("서블릿");
		System.out.println("ArrayList...");
		print(list1);
		
		List<String> list2 = new LinkedList<String>();
		list2.add("서울");
		list2.add("부산");
		list2.add("대구");
		System.out.println("\nLinkedList...");
		print(list2);
		
	}
	
	public static void print(List<String> list) {
		for(String s : list) {
			System.out.print(s +"  ");
		}
		System.out.println();
	}
}

2021.07.30 - [쌍용강북교육센터/7월] - Q 0729_Ex001~Ex002_List

 

Q 0729_Ex001~Ex002_List

package ex0729; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /* - List 인터페이스 : 순서가 있다. : 배열과 유사한 구조 : 가변 길이(저장..

development-writing.tistory.com

내가 여기에서 왜 업캐스팅을 하지? 하고 오늘 수업할 때 선생님께 질문했더니, 예제를 통해 그 이유를 알려주셨다.

업캐스팅을 안했으면 ArrayList 와 LinkedList 두 개를 선언하고 print() 메소드를 정의할 때,  매개변수에 

public static void print(ArrayList<String> list1)

public static void print(LinkedList<String> list2) 이렇게 해야 되서, 업캐스팅해서 한 번만 적으면 코드가 짧아진다.


package ex0730;

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

public class Ex02_List {
	public static void main(String[] args) {
		ArrayList<String> list1 = new ArrayList<>();
		LinkedList<String> list2 = new LinkedList<>();
		
		timeTest1("LinkedList", list2);
		timeTest1("ArrayList", list1); // 앞줄과 순서를 바꿔보면 시간 차이가 보임
		System.out.println("-------------------------------");
		
		timeTest2("LinkedList", list2);
		timeTest2("ArrayList", list1);
	}
	
	public static void timeTest1(String cls, List<String> list) {
		long s, e;
		
		s = System.nanoTime();
		for(int i=0; i<20000; i++) {
			list.add( String.valueOf(i) );
				// 가장 뒤에 추가하는 경우 실행 순서에 따라 차이가 있으나 ArrayList가 빠름
		}
		e = System.nanoTime();
		
		System.out.printf("%s, 시간:%,d\n", cls, (e-s));
		
		list.clear();
	}

	public static void timeTest2(String cls, List<String> list) {
		long s, e;
		
		s = System.nanoTime();
		for(int i=0; i<20000; i++) {
			list.add( 0, String.valueOf(i) ); // 앞 추가 삭제시 LinkedList 가 빠름
		}
		e = System.nanoTime();
		
		System.out.printf("%s, 시간:%,d\n", cls, (e-s));
		
		list.clear();
	}
}

이것은 ArrayList와 LinkedList 검색 시 걸리는 시간을 비교해본 것이다. 

'쌍용강북교육센터 > 7월' 카테고리의 다른 글

Q 0729_Ex001~Ex002_List  (0) 2021.07.30
0729_Ex06~Ex09_system : Java API  (0) 2021.07.29
0729_ConsoleEx_콘솔 입력  (0) 2021.07.29
0729_Ex01~Ex05_Generic  (0) 2021.07.29
0728_Ex11~Ex17_generic : 제네릭  (0) 2021.07.29
package ex0729;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/*
 - List 인터페이스
 	: 순서가 있다.
 	: 배열과 유사한 구조
 	: 가변 길이(저장 공간이 부족하면 자동으로 공간이 늘어남)
 	: 중복적인 요소도 추가 가능
 	: 중간에 데이터를 추가하거나 삭제도 가능
 	: 주요 구현 클래스 - ArrayList, Vector, LinkedList, Stack 등..
 	: 동기화 지원 : Vector - 다중 스레드 환경에서 안전
 	: 동기화 지원 안함 : AraayList, LinkedList - 다중 스레드 환경에서 안전하지 않음(속도 빠름)
 */
public class Ex001_List {
	public static void main(String[] args) {

		List<String> list = new ArrayList<String>(); // up casting
		String s;

		// 마지막에 요소 추가
		list.add("서울");
		list.add("부산");
		list.add("인천");
		list.add("광주");
		list.add("서울"); // 요소의 중복 가능
		list.add("대전");

		System.out.println(list);

		// 2인덱스에 데이터 추가
		list.add(2, "대구");
		System.out.println(list);

		// 데이터 개수 ?
		System.out.println("개수 : " + list.size());

		// 처음 데이터
		s = list.get(0);
		System.out.println("처음 : " + s);

		// 두번째
		s = list.get(1);
		System.out.println("두번째 : " + s);

		// 마지막
		s = list.get(list.size() - 1);
		System.out.println("마지막 : " + s);

		// 처음에 한국 추가
		list.add(0, "한국");
		System.out.println(list);

		// 처음의 데이터를 대한민국으로 수정
		list.set(0, "대한민국");
		System.out.println(list);

		int idx;
		// 인천은 몇 번째 인덱스에 ?
		idx = list.indexOf("인천");
		System.out.println("인천 인덱스 : " + idx);

		idx = list.indexOf("세종"); // 없으면 -1
		System.out.println("세종 인덱스 : " + idx);

		idx = list.indexOf("서울");
		System.out.println("서울(처음부터 검색) : " + idx);

		idx = list.lastIndexOf("서울");
		System.out.println("서울(뒤부터 검색) : " + idx);

		// 부산 존재 여부
		System.out.println("부산이 존재합니까 ? " + list.contains("부산"));

		// 대한민국 삭제
		// list.remove("대한민국");
		list.remove(0);
		System.out.println(list);

		System.out.println("전체 출력 - 1");
		for (int i = 0; i < list.size(); i++) {
			System.out.print(list.get(i) + "  ");
		}
		System.out.println();

		System.out.println("전체 출력 - 2");
		for (String str : list) {
			System.out.print(str + "  ");
		}
		System.out.println();

		System.out.println("전체 출력 - 3");
		// 반복자. 순방향만 가능
		Iterator<String> it = list.iterator(); // 하나씩 데이터를 꺼낸다.
		while (it.hasNext()) { // 데이터가 존재하면 true, 없으면 false
			String str = it.next(); // 있는 곳의 데이터를 돌려주고 다음으로 간다.
			System.out.print(str + "  ");
		}
		System.out.println();

		System.out.println("역순 - 1");
		for (int i = list.size() - 1; i >= 0; i--) {
			System.out.print(list.get(i) + "  ");
		}
		System.out.println();

		System.out.println("역순 - 2");
		// ListIterator : 순방향과 역방향 모두 이동 가능
		// 반복자의 위치를 가장 마지막으로 이동
		ListIterator<String> it2 = list.listIterator(list.size());
		while (it2.hasPrevious()) {
			String str = it2.previous();
			System.out.print(str + "  ");
		}
		System.out.println();

		// 모두 지우기
		list.clear();
		System.out.println("모두 삭제 후 개수 : " + list.size());

	}
}

List 인터페이스

  • 순서가 있는 컬렉션
  • 목록에서 각 요소가 삽입되는 위치를 제어 할 수 있다.
  • 요소를 인덱스로 관리하며, 인덱스로 요소를 검색하거나 삭제 할 수 있다.
  • 동일한 요소(객체)를 중복해서 저장할 수 있다.
  • List 컬렉션은 객체 자체가 저장되는 것이 아니라 객체의 번지를 참조한다.
  • null도 저장이 가능하며, null을 저장한 경우에는 해당 인덱스는 객체를 참조하지 않는다.
  • 배열과 유사한 구조
  • 가변 길이로 저장 공간이 부족하면 자동으로 공간이 늘어난다.

 

List를 하기 위해서 제네릭을 배운 것!

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

String인 자료형을 저장할 리스트를 생성

add 메소드로 요소를 추가 할 수 있다.

size 메소드로 리스트의 크기를 알 수 있다.

set 메소드로 원하는 위치에 리스트를 변경 할 수 있다.

contains 메소드로 리스트에서 검색 후 boolean으로 반환해준다.

package ex0729;

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

public class Ex002_List {

	public static void main(String[] args) {
		List<String> list1 = new ArrayList<String>();
		list1.add("서울");
		list1.add("부산");
		list1.add("대구");

		List<String> list2 = new ArrayList<String>();
		list2.add("강원");
		list2.add("경기");
		list2.add("경상");

		// list2에 list1의 모든 데이터를 추가
		list2.addAll(list1);
		System.out.println(list2);

		// List<String> => String[]
		String[] ss = list2.toArray(new String[list2.size()]);
		System.out.println("리스트를 배열로 복사...");
		for (String s : ss) {
			System.out.print(s + "  ");
		}
		System.out.println();

		// String[] => List<String>
		List<String> list3 = Arrays.asList(ss);
		System.out.println("배열을 리스트로 복사 후 : " + list3);

		// subList(a, b) : a인덱스에서 b-1인덱스까지의 부분 List
		List<String> list4 = list3.subList(1, 4);
		System.out.println(list4); // [경기, 경상, 서울]

		// 전체 삭제
		list1.clear();
		System.out.println("전체 삭제 후 : " + list1.size());

		// list2의 데이터중 [경상, 서울, 부산] 삭제
		System.out.println("삭제 전 : " + list2);
		list2.subList(2, 5).clear();
		
		System.out.println("삭제 후 : " + list2);
		
		
	}

}

list의 메소드를 익히고 적절하게 사용해보도록 하자!

 

배열과 ArrayList

  • 배열은 한 번 크기가 결정되면 배열의 크기를 변경할 수 없다.
  • 배열의 처음이나 중간에 데이터를 삽입하는 경우, 기존 데이터가 존재하면 데이터를 덮어쓰기 때문에 기존 데이터는 사라진다.
  • ArrayList는 가변 길이의 자료구조로 데이터의 검색에 유리하며, 추가 또는 삭제에는 성능을 고려해야 한다.
  • 리스트의 처음, 끝, 중간에 자료를 추가 또는 삭제하는 기능을 제공한다.

근데 왜 

List<String> list = new Arraylist<>(); 이렇게 업 캐스팅 하는 건쥐..?

'쌍용강북교육센터 > 7월' 카테고리의 다른 글

0730_Ex01~Ex02_List  (0) 2021.07.30
0729_Ex06~Ex09_system : Java API  (0) 2021.07.29
0729_ConsoleEx_콘솔 입력  (0) 2021.07.29
0729_Ex01~Ex05_Generic  (0) 2021.07.29
0728_Ex11~Ex17_generic : 제네릭  (0) 2021.07.29
package ex0729;

public class Ex06_system {

	public static void main(String[] args) {
		String s;

		s = System.getProperty("os.name");
		System.out.println("운영체제 : " + s);

		s = System.getProperty("file.encoding");
		System.out.println("character set : " + s); // MS949(euc-kr 유사)

		s = System.getProperty("java.version");
		System.out.println("자바 버전 : " + s);

		s = System.getProperty("user.dir");
		System.out.println("현재 작업 경로 : " + s);

		
	}

}

package ex0729;

import java.util.Enumeration;
import java.util.Properties;

public class Ex07_system {

	public static void main(String[] args) {
		// 시스템 환경 설정 정보(운영체제, 인코딩, 작업 경로 등...)
		Properties p = System.getProperties();
		Enumeration<?> e = p.propertyNames();

		while (e.hasMoreElements()) {
			String key = (String) e.nextElement();
			String value = p.getProperty(key);
			System.out.println(key + "->" + value);
		}

	}

}

이런저런것들 볼 수 있음...

package ex0729;

import java.util.Scanner;

public class Ex08_system {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n;

		try {
			while (true) {
				System.out.print("정수 ? ");
				n = sc.nextInt();

				if (n == 0) {
					System.exit(0); // 프로그램 강제 종료. finally 블록은 실행 안됨.
					// return; // finally 블럭은 실행됨.
					// return 은 main() 메소드를 빠져 나가는 것으로
					// main()이 종료된다고 프로그램이 종료되는 것은 아니다.
					// main()은 프로그램의 진입점이지만 종료점은 아니다.
				}

				System.out.println("입력 값 : " + n);
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("final block ...");
			sc.close();
		}
		System.out.println("end...");
		
	}

}

'쌍용강북교육센터 > 7월' 카테고리의 다른 글

0730_Ex01~Ex02_List  (0) 2021.07.30
Q 0729_Ex001~Ex002_List  (0) 2021.07.30
0729_ConsoleEx_콘솔 입력  (0) 2021.07.29
0729_Ex01~Ex05_Generic  (0) 2021.07.29
0728_Ex11~Ex17_generic : 제네릭  (0) 2021.07.29
package ex0729;

import java.io.Console;

public class ConsoleEx {

	public static void main(String[] args) {
		// 콘솔 입력을 지원하는 클래스로 JDK 6이상 부터 가능. 이클립스에서는 테스트 불가.
		Console c = System.console();
		if( c==null) {
			System.out.println("Console을 지원하지 않습니다.");
			System.exit(0);
		}
		
		String id = c.readLine("%s", "ID : ");
		char[] pwd = c.readPassword("%s", "Password : ");
		
		String s = new String(pwd); // char[]을 String으로
		
		System.out.println("아이디 : " + id);
		System.out.println("패스워드 : " + s);

	}

}

위 소스는 이클립스로 실행이 안되기 때문에 cmd 창에서 확인해보았다.

패스워드를 입력할 때 보이지 않게끔 해주는 거 보려고 한 코드!

'쌍용강북교육센터 > 7월' 카테고리의 다른 글

Q 0729_Ex001~Ex002_List  (0) 2021.07.30
0729_Ex06~Ex09_system : Java API  (0) 2021.07.29
0729_Ex01~Ex05_Generic  (0) 2021.07.29
0728_Ex11~Ex17_generic : 제네릭  (0) 2021.07.29
0728_Ex01~Ex03_exception : 예외처리  (0) 2021.07.29
package ex0729;

public class Ex01 {
	public static void main(String[] args) {
		Test1<Integer> t = new Test1<>();
		
		t.append(10);
		t.append(20);
		t.append(30);
		
		// t.append("자바"); // 컴파일 오류
		
		Integer i = t.get(2);
		System.out.println(i);
	}
}

class Test1<E> {
	private Object[] data;
	private int count;

	public Test1() {
		data = new Object[10];
	}

	public void append(E e) {
		if(count >= data.length) {
			// ArrayIndexOutOfBoundsException() : unchecked 예외. 배열의 첨자가 초과한 경우 발생
			throw new ArrayIndexOutOfBoundsException("요소의 개수를 초과 했습니다.");
		}
		
		data[count++] = e;
	}
	
	@SuppressWarnings("unchecked") // 부적절한 컴파일러의 경고를 제거하기 위해 사용
	public E get(int index) {
		if(index >= count) {
			throw new ArrayIndexOutOfBoundsException(index);
		}
		
		// 제네릭으로 casting 하면 경고가 발생
		return (E) data[index];
	}
	
	public int getCount() {
		return count;
	}
	
}

@SuppressWarnings("unchecked") // 부적절한 컴파일러의 경고를 제거하기 위해 사용

하지만 정확하게 알 때만 사용. 거의 사용하지 않는다!!

<위 코드는 아래와 비교해서 이해할 것!>

package ex0729;

public class Ex02 {
	public static void main(String[] args) {
		Test2<Integer> t = new Test2<>();
		t.append(10);
		t.append(20);
		t.append(30);

		// Integer[] i = t.get(); // 런타임 오류. ClassCastException. 배열은 강제 형변환이 안됨.

		// Cast가 필요
		Object[] oo = t.get();
		for (Object o : oo) {
			Integer i = (Integer) o;
			System.out.println(i);
		}
		// 제네릭배열은 의미가 없다.
	}
}

class Test2<E> {
	private E[] data;
	private int count;

	@SuppressWarnings("unchecked")
	public Test2() {
		// 제네릭 배열 메모리 할당
		// data = new E[10]; // 컴파일 오류
		data = (E[]) new Object[10]; // 제네릭은 Object로 메모리할당을 해야 함.
	}

	public void append(E e) {
		if (count >= data.length) {
			throw new ArrayIndexOutOfBoundsException("배열 요소의 개수를 초과 했습니다.");
		}

		data[count++] = e;
	}

	public E[] get() {
		return data;
	}

	public int getCount() {
		return count;
	}
}

위에서는 Object로 배열을 만들어서 생성자에서 배열의 메모리 할당을 해주었는데,

밑에서는 제네릭클래스에서 제네릭 배열을 만들었다. 

배열의 선언을 위해 생성자에서 할당하려고 했을 때 

data = new E[10]; 은 컴파일 오류가 발생했다. 메모리 할당을 위해서는 Object로 해야 했다. 그래서 배열 메모리 할당 후에 data에 다시 제네릭타입으로 캐스팅하고 넣었다. 여기서 느낌표가 발생해서 다시 

@SuppressWarnings("unchecked") 를 넣어줬다.

 

메인 클래스에서 제네릭타입을 Integer로 해서 객체를 생성한 후 Integer 값들을 3개를 넣었는데 그 배열을 다시 만들으려 했으나

Integer[] i = t.get(); // 런타임 오류. ClassCastException. 배열은 강제 형변환이 안된다.

결국 이 배열을 받기 위해서는 Object로 배열을 생성해서 받아야 했다.

 

package ex0729;

public class Ex03 {
	public static void main(String[] args) {
		Test3<Integer> t = new Test3<>();
		
		Integer[] i = {10,20,30};
		
		t.set(i);
		
		Integer[] i2 = t.get();
		System.out.println(i2[1]);
		
	}
}

class Test3<E> {
	private E[] data;
	
	public void set(E[] data) {
		this.data = data;
	}
	
	public E[] get() {
		return data;
	}
}

 

 

package ex0729;

public class Ex04 {
	public static void main(String[] args) {
		Test4<Number> ob1 = new Test4<>();	
		ob1.set(new Integer(30)); // 타입 매개변수의 상속 관계는 성립
		System.out.println(ob1.get());
		
		// Number n = ob1.get();
		// Integer i = ob1.get(); // 컴파일 오류
		// Integer i = (Integer)ob1.get();
		
		// Number n = new Integer(30); // 업 캐스팅
		Test4<Integer> ob2 = new Test4<>();
		ob2.set(new Integer(30));
		// Test4<Number> ob3 = ob2; // 컴파일 오류. 제네릭은 업캐스팅 불가.
		
		
	}
}

class Test4<T> {
	private T t;
	
	public void set(T t) {
		this.t=t;
	}
	
	public T get() {
		return t;
	}
}

제네릭 타입을 Number로 주었기 때문에 

Integer i = ob1.get(); 은 컴파일 오류이고 강제적으로 캐스팅을 한 후에는 가능하다.

Integer i = (Integer)ob1.get();

Test4<Number> ob3 = ob2; 제네릭은 업캐스팅이 불가해서 컴파일 오류이다.

 

제네릭은 컴파일 단계에서 타입 안정성을 위해 지원하므로 기본적으로 다형성을 갖지 않는다. 

package ex0729;

public class Ex05 {
	public static void main(String[] args) {
		Test5<Integer> ob = new Test5<>();
		ob.set(30);
		
		// Test5<Number> ob2 = ob; // 컴파일 오류. 상속관계가 아님.
		// 제네릭은 같은 데이터 타입만 가능. 훨씬 안정적이다.
		
		// 제네릭 - 와일드 카드
		// ? : 모든 클래스나 인터페이스가 가능
		// 제네릭 타입에 의존적이지 않는 메소드등을 호출
		Test5<?> ob2 = ob;
		ob2.print();
		
		// ob2.set(new Integer(30) ); // 컴파일 오류. 자료형이 결정되지 않은 상태이므로
	}
}

class Test5<T> {
	private T t;
	
	public void set(T t) {
		this.t=t;
	}
	
	public T get() {
		return t;
	}
	
	public void print() {
		System.out.println(t);
	}
}

제네릭에 다형성을 갖도록 만들기 위해 와일드 카드를 사용한다.

제네릭 타입의 클래스를 파라미터로 사용할 때 구체적인 타입이 정해지지 않는 경우에 사용한다.

 

제네릭타입<?> 

  • 제한 없다.
  • 타입 파라미터를 대치하는 구체적인 타입으로 ?에는 모든 클래스나 인터페이스 타입이 올 수 있다.

Test5<?> ob2 = ob;
ob2.print(); // 제네릭 타입에 의존적이지 않은 메소드는 호출할 수 있지만 

ob2.set(); // 이것과 같은 제네릭 타입이 들어가는 메소드는 호출할 수 없다. 컴파일 오류,

'쌍용강북교육센터 > 7월' 카테고리의 다른 글

0729_Ex06~Ex09_system : Java API  (0) 2021.07.29
0729_ConsoleEx_콘솔 입력  (0) 2021.07.29
0728_Ex11~Ex17_generic : 제네릭  (0) 2021.07.29
0728_Ex01~Ex03_exception : 예외처리  (0) 2021.07.29
0727_패키지  (0) 2021.07.27
package ex0728;

// import java.util.Arrays;

public class Ex11_generic {
	public static void main(String[] args) {
		Object[] obj = new Object[5];

		// Object는 모든 클래스 객체를 참조할 수 있다. (up casting)
		obj[0] = new String("서울");
		obj[1] = new String("부산");
		obj[2] = new Integer(30);
		obj[3] = new Integer(50);
		obj[4] = new String("인천");

		// Arrays.sort(obj); // ClassCastException 런타임 오류

		// String s = (String)obj[2]; // ClassCastException 런타임 오류
		if (obj[1] instanceof String) { // obj[2] 너 String 형이니?
			String s = (String) obj[1]; // 스트링 형이면 다운캐스팅하고
			System.out.println(s + ":" + s.length()); // 출력하고 : 길이도 출력해
		}

		for (Object o : obj) {
			System.out.println(o);
		}

	}
}

Object는 모든 클래스들의 조상이므로 (시조라고 해야하나 ㅋㅋ)

자식들은 Object클래스로 up casting이 가능하다. 지금 이 코드는 숫자나 문자열 모두 그냥 Object에 넣었다.

이럴 경우 데이터타입에 관계없이 모든 것을 넣을 수 있다.

하지만 자료형이 다 제각각이므로 Arrays.sort(obj); 과 같은 메소드를 사용하면 런타임 오류가 발생한다. 

 

Integer 30을 강제로 캐스팅 하면 ClassCastException 이라는 런타임 오류가 발생한다. 그래서 A instanceof B 를 써서 배열A에 들어가 있는 데이터타입이 B 이면 강제로 다운캐스팅(다운캐스팅은 업캐스팅한 것만 가능)하고 출력하라고 밑에서 if문을 쓴 것이다.


package ex0728;

public class Ex12_generic {
	public static void main(String[] args) {
		Test2 t1 = new Test2();
		// t1.set(new String("서울"));
		t1.set("서울");
		String s = (String)t1.get();
		System.out.println(s);
		
		// Integer i1 = (Integer) t1.get(); // ClassCastException 런타임 오류.
		
		Test2 t2 = new Test2();
		t2.set(30);
		Integer i2 = (Integer)t2.get();
		System.out.println(i2);
	}
}

class Test2 {
	private Object ob;
	
	public void set(Object ob) {
		this.ob = ob;
	}
	
	public Object get() {
		return ob;
	}
}

t1의 객체는 String형을 저장하고

t2의 객체는 Integer형을 저장했다.

그냥

System.out.println(t1.get());
System.out.println(t2.get());

이면 상관없지만

s, i2에 넣을 때는 s의 데이터타입인 String으로 다운캐스팅 i2의 데이터타입인 Integer로 다운캐스팅을 해야 한다.

 


본격적으로 Generic에 대해 알아보자.

 

다양한 타입의 객체를 다루는 클래스나 인터페이스에서 사용할 데이터 타입을 인스턴스를 생성할 때 결정하는 것으로 JDK 5.0부터 지원한다.

  • 성능 저하를 유발하는 강제 캐스팅을 줄일 수 있다.
  • 컴파일 할 때 타입 오류를 체크하므로 객체 타입의 안정성을 높인다.
  • 반복적인 코드를 줄일 수 있으며, 재사용성 증가로 유지보수가 편리하다.

 

package ex0728;

public class Ex13_generic {
	public static void main(String[] args) {
		Test3<String> t1 = new Test3<String>();
		t1.set("서울");
		// t1.set(50); // 컴파일 오류
		String s = t1.get();
		System.out.println(s);
		
		// Integer i1 = (Integer)t1.get(); // 컴파일 오류. 미연에 방지 할 수 있다!
		
		Test3<Integer> t2 = new Test3<>(); // new 뒤에 <>에서는 자료형 생략가능. new Test3<Integer> 에서 Integer생략
		t2.set(30);
		Integer n = t2.get();
		System.out.println(n);
		
/*		
		Test3 t3 = new Test3(); // 가능하지만 경고 발생. 제너릭은 Object로 처리.
		t3.set("서울");
		t3.set(50);
*/
		
		
	}
}

class Test3<T> { // <> 안에는 마음대로 이름을 줄 수 있다. 
	private T t; // T에 자료형은 String, Integer, Long ...등이 올 수 있음. 아직 정해지지 않았다.
	public void set(T t) {
		this.t = t;
	}
	
	public T get() {
		System.out.println(t.getClass()); // 무슨 클래스인지 볼 수 있다.
		return t;
	}
}

객체를 생성할때 <> 안에 어떤 데이터타입만 저장할 것인지 설정을 해서 생성할 수 있다.

Test3<String> t1 = new Test3<String>();

 

t1.set(50); 으로 주면 컴파일 오류가 생기기 때문에 안정적으로 코딩할 수 있다.

 

제네릭을 설정하지 않고 그냥 

Test3 t3 = new Test3(); 으로 객체를 생성하면 경고가 발생한다. 이때 제네릭은 Object로 처리되기 때문에 

t3.set("서울");

t3.set(50); 

모두 넣을 수 있다. 하지만 비추천.

 

제네릭을 만들 때 <> 안에 마음대로 이름을 줄 수 있으나 관습적으로 대문자 알파벳 한 문자를 사용하고

E : Element

K : Key

N : Number

T : Type

V : Value

S, U, V : 2nd, 3rd, 4th types..

으로 사용한다.

 

마지막에 확인해보면 t1의 클래스는 <String>으로 줬기 때문에 String으로 뜨고, t2는 Integer로 준 것을 확인 할 수 있다.


package ex0728;

public class Ex14_generic {
	public static void main(String[] args) {
		Test4<String, Integer> ob = new Test4<>();
		
		ob.set("자바", 100);
		ob.print();
		
		ob.set("스프링", 200);
		ob.print();
	}
}

class Test4<T, U> {
	private T t;
	private U u;
	
	public void set(T t, U u) {
		this.t = t;
		this.u = u;
	}
	
	public void print() {
		System.out.println("T : "+t.getClass().getName()+", "+t);
		System.out.println("U : "+u.getClass().getName()+", "+u);
	}
	
	
}

제네릭 클래스에 멀티 타입 파라미터를 준 경우이다. 만들때 <String, Integer>라고 했으니 T의 자료형은 String형이되고 U의 자료형은 Integer형이 된다.


package ex0728;

public class Ex15_generic {
	public static void main(String[] args) {
		Test5<Integer> ob = new Test5<>();
		ob.set(30);
		Integer i = ob.get();
		System.out.println(i);
		
		// Test5<String> ob2 = new Test5<>(); // 컴파일 오류 발생.
		// Number를 상속받은 class가 아니기 때문이다.
		
	}
}

// 제한된(한정된) 타입 파라미터(bounded type parameter)
// Number를 상속받은 클래스만 가능 (Integer, Long, Double ...)
class Test5<T extends Number> {
	private T t;
	public void set(T t) {
		this.t=t;
	}
	
	public T get() {
		return t;
	}
}

제한된 타입 파라미터만을 받도록 설정한 제네릭 클래스.

T extends Number를 통해 Number를 상속받았기 때문에 그 클래스에 포함되는 것들만 파라미터로 받을 수 있다.

package ex0728;

public class Ex16_genericMethod {
	public static void main(String[] args) {
		Test6 t = new Test6();
		
		t.print("자바");
		t.print(20);
		
		t.disp(30);
		// t.disp("자바"); // 컴파일 오류
	}
}

// generic Method 
class Test6 {
	public <U> void print(U u) {
		System.out.println(u.getClass().getName() + ", " + u);
	}

	public <U extends Number> void disp(U u) {
		System.out.println(u.getClass().getName() + ", " + u);
	}
}

제네릭 메소드 타입 파라미터를 하나 이상 갖는 메소드를 말한다.

선언 방법은 리턴 타입 앞에 <> 기호를 추가하고 <> 기호 안에 타입 파라미터를 기술 한 후 리턴 타입과 매개 변수타입에서 타입 파라미터를 사용한다.

disp(U u) 메소드의 경우 받는 자료형을 Number를 상속받은 것들만 가능하게 설정했으므로 

t.disp("자바"); 의 경우 컴파일 오류이다.

package ex0728;

public class Ex17_generic {
	public static void main(String[] args) {
		TestImpl7<Integer> ob1 = new TestImpl7<>();
		ob1.print(10);
		
		DemoImpl7 ob2 = new DemoImpl7();
		ob2.print("자바");
		
	}
}

// 제네릭 인터페이스
interface Test7<T> {
	public void print(T t);
}

// 구현 클래스-1
class TestImpl7<T> implements Test7<T> {
	@Override
	public void print(T t) {
		System.out.println(t);
		
	}
	
}

// 구현 클래스-2
class DemoImpl7 implements Test7<String> {
	@Override
	public void print(String t) {
		System.out.println(t);
	}
	
}​

제네릭 인터페이스를 구현할 때 위의 2가지 방법으로 구현할 수 있다.

1의 경우 자료형을 객체를 생성할 때 결정한 방법이고

2의 경우 구현 클래스에서 자료형을 결정한 방법이다.

 

'쌍용강북교육센터 > 7월' 카테고리의 다른 글

0729_ConsoleEx_콘솔 입력  (0) 2021.07.29
0729_Ex01~Ex05_Generic  (0) 2021.07.29
0728_Ex01~Ex03_exception : 예외처리  (0) 2021.07.29
0727_패키지  (0) 2021.07.27
0727_Ex06~Ex08_enum : 열거형  (0) 2021.07.27

+ Recent posts