Collection - Set

Zino·2022년 12월 29일

Java

목록 보기
24/26

Set

= 집합

  • 저장 순서가 유지되지 않고, 중복 객체도 저장하지 못하게 하는 자료 구조
    null도 중복을 허용하지 않기 때문에 1개의 null만 저장
    구현 클래스로 HashSet, LinkedHashSet, TreeSet이 있음


Set 계열 주요 메소드


HashSet

  • Set에 객체를 저장할 때 hash함수를 사용하여 처리 속도가 빠름
    동일 객체 뿐 아니라 동등 객체도 중복하여 저장하지 않음

LinkedHashSet

  • HashSet과 거의 동일하지만 Set에 추가되는 순서를 유지한다는 점이 다름

예제

public class Setservice {
	
	// set(집합)
	// - 순서를 유지하지 않음(== 인덱스 없음)
	// - 중복을 허용하지 않는다.( + null도 중복X, 1개만 저장 가능)
	
	
	
	// *** Set이 중복을 확인하는 방법 ***
	// 컬렉션은 객체만 저장할 수 있음 ( Set은 컬렉션이기 때문에 객체만 저장)
	// -> 객체가 가지고있는 필드 값이 모두 같으면 중복으로 판단 
	// -> 이 때 필드값이 모두 같은지 비교하기 위해서
	//	  객체에 "equals" 가 반드시!!! 오버라이딩 되어야 한다.
	
	public void ex1() {
		
		Set<String> set = new HashSet<String>(); 
		 
		// HashSet : Set의 대표적인 자식 클래스
		// 사용조건 1 : 저장되는 객체 equals() 오버라이딩 필수
		// 사용조건 2 : 저장되는 객체 hashCode() 오버라이딩 필수
		
		// String 은 굉장히 완성도 높은 클래스로, 
		// 이미 equals, hashCode가 오버라이딩 되어있음 
		// 다른 클래스 만들때는 equals, hashCode를 오버라이딩 해야함.
		
		// set.add(String e) : 추가
		
		set.add("네이버");
		set.add("카카오");
		set.add("쿠팡");
		set.add("배민");
		set.add("배민");
		set.add("배민");
		set.add("배민");
		set.add("배민");
		set.add(null);
		set.add(null);
		set.add(null);
		set.add(null);
		
		System.out.println(set);
		
		// 출력 --> [null, 카카오, 네이버, 쿠팡, 배민]
		// 순서 유지 X 
		// 중복값 X (null도 중복 X)

		// size() : 저장된 데이터의 개수 반환
		System.out.println("저장된 데이터의 수 : " + set.size());
		
		// remove(String e) : Set에 저장된 객체 중 매개변수 e와 
		// 					  필드값이 같은 객체를 제거 
		//			+ Hash라는 단어가 포함된 Set이면 hashCode()도 같아야함.
		
		System.out.println(set.remove("배민")); // 삭제하면 true / 못지웠음 false
		System.out.println(set.remove("당근")); // 삭제하면 true / 못지웠음 false
		
		System.out.println(set);// 제거 확인 용도
		
		// List는 index가 있어서 get()로 요소 하나 얻어올 수 있었지만
		// Set은 순서가 없어서 저장된 객체 하나를 얻어올 수 있는 방법이 없다!
		// -> 대신에 Set 전체의 데이터를 하나씩 반복적으로 얻어올 순 있다.
		
		// 1. Iterator(반복자)
		// - 컬렉션에서 제공하는 컬렉션 객체 반복 접근자
		// (컬렉션에 저장된 데이터를 임의로 하나씩 반복적으로 꺼내는 역할)
		Iterator<String> it = set.iterator();
		// set.iterator : Set을 Iterator 하나씩 꺼내갈 수 있는 모양으로 변환
		
		while(it.hasNext()) {// -> 다음 값이 있는지?
			
			// it.hasNext() : 다음 값이 있으면 true 반환
			// it.next() : 다음 값(객체)을 얻어옴.
			String temp = it.next();
			
			System.out.println(temp);
		}
		
		System.out.println("====================================");
		
		//향상된 for문 사용 
		//for( 하니씩 꺼내서 저장할 변수 : 컬렉션)
		for(String temp : set) {
			System.out.println(temp);
		}
		
	}
	
	public void ex2() {
		
		// Hash 함수 : 입력된 단어를 지정된 길이의 문자열로 변환하는 함수 (중복X)
		// ex) 입력: 111 -> "asdfg" (5글자)
		// ex) 입력: 123456789 -> "qrwer" (5글자)
		// == 압호화에 사용
		// 일정한 길이의 랜덤값 생성, 중복되지 않음
		
		// hashCode() : 필드 값이 다르면 중복되지 않는 숫자르 만드는 메서드
		// -> 왜 만들까? 빠른 데이터 검색을 위해서 (객체가 어디에 있는지 빨리 찾음)
		
		// HashSet() : 중복 없이 데이터 저장(Set)하고 데이터 검색이 빠름(Hash)
		
		Member mem1 = new Member("user01", "pass01", 30);
		Member mem2 = new Member("user01", "pass01", 30);
		Member mem3 = new Member("user02", "pass02", 20);
		
		System.out.println( mem1 == mem2); // 참조형이기때문에 주소 비교
		// 얕은 복사 경우가 아니라면 다 false
		
		if( mem1.getId().equals(mem2.getId())){
			if( mem1.getPw().equals(mem2.getPw())){
				if(mem1.getAge() == mem2.getAge()) {
					System.out.println("같은 객체입니다 (true)");
				}
			}
		}
		
		// ==> 매번 이렇게 비교하기 힘듬 
		// ==> equals() 메소드 오버라이딩
		
		System.out.println("========================");
		
		System.out.println(mem1.equals(mem2)); // mem1, mem2의 필드가 같은가?
		// => ture
		System.out.println(mem1.equals(mem3)); // mem1, mem3의 필드가 같은가?
		// => false
	}

	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", 50));
		memberSet.add(new Member("user04", "pass04", 20));
		memberSet.add(new Member("user04", "pass04", 20));
		
		
		for( Member mem : memberSet) {
			System.out.println(mem);
		}
		//Member [id=user03, pw=pass03, age=50]
		//Member [id=user01, pw=pass01, age=30]
		//Member [id=user02, pw=pass02, age=40]
		//Member [id=user04, pw=pass04, age=20]
		
		// => 중복이 제거됨
		// - hashCode를 비교하는 것이기 때문에,
		//   hashCode() 오버라이딩이 안되어있으면 중복 검사가 안된다.

		Member mem1 = new Member("user01", "pass01", 30);
		Member mem2 = new Member("user01", "pass01", 30);
		Member mem3 = new Member("user02", "pass02", 20);
		
		
		System.out.println(mem1.hashCode());
		System.out.println(mem2.hashCode());
		System.out.println(mem3.hashCode());
		
		// -1142504125
		// -1142504125
		// -1142513703
	}
	
	public void ex4() {
		// Wrapper 클래스 : 기본자료형 -> 객체로 포장하는 클래스
		
		// - 컬랙션에 기본 자료형 값을 저장하고 싶을 때 사용
		// - 기본 자료형에 없던 추가 기능, 값을 이용하고 싶을 때 사용
		
		// <Wrapper 클래스 종류>
		// int -> Integer
		// char -> Charactor
		// Double, Boolean, Byte , Short, Float
		
		int iNum = 10;
		double dNum = 3.14;
		
		// 기본 자료형 -> 포장
		Integer w1 = new Integer(iNum);
						// 삭제선
		Double w2 = new Double(dNum);
		
		// Wrapper 클래스 활용
		System.out.println("int 최대값 : " + w1.MAX_VALUE); // static
		System.out.println("int 최소값 : " + w1.MIN_VALUE); // static
		
		System.out.println("double 최대값 : " + w2.MAX_VALUE); // static
		System.out.println("double 최소값 : " + w2.MIN_VALUE); // static
		
		System.out.println("======== static 방식으로 Wrapper클래스 사용 =========");
		System.out.println("int 최대값 :" + Double.MAX_VALUE);
		System.out.println("int 최소값 :" + Double.MIN_VALUE);
		
		//****************************************************************
		
		// parsing : 데이터의 형식을 변환
		
		// String 데이터를 기본 자료형으로 변환
		
		int num1 = Integer.parseInt("100");
		double num2 = Double.parseDouble("1.23456");
		
		System.out.println(num1);
		System.out.println(num2);
		
		System.out.println(num1 + num2);
		
		//****************************************************************
	}
	
	public void ex5() {
		
		//Wrapper 클래스의 AutoBoxing / AutoUnboxing
		
		Integer w1 = new Integer(100);
		
		Integer w2 = 100;
		Integer w3 = 200;
		//(Integer)  (int -> Integer) 자동포장
		//				AutoBoxing
		
		// w2와 100은 원래 연산이 안되어야 하지만
		// Integer는 int의 포장형식이라는걸 Java가 인식하고 있음
		// -> 위와 같은 경우 int를 Integer로 자동 포장 해준다.
		
		System.out.println("w2 + w3 : " + (w2 + w3));
		
		// w2 + w3 == 객체 + 객체 ==> 원래 불가능
		// 하지만 Integer는 int의 포장형태라는걸 Java가 인식하고 있음
		// -> 연산 시 포장을 자동으로 벗겨냄.
		
		// Integer + Integer -> int + int (자동포장해제)
							 // AutoUnBoxing
	}
	
	public void lotto() {
		
		// 로또 번호 생성기 Ver2
		
		// HashSet
		// LinkedHashSet // 순서 유지 set
		// TreeSet(오름차순)
		
		//Set<Integer> lotto = new HashSet<Integer>(); // 순서 유지X, 중복제거만 
		//Set<Integer> lotto = new LinkedHashSet<Integer>();// 순서 유지 set
		Set<Integer> lotto = new TreeSet<Integer>();// 순서 유지 set
		//Integer는 equals(), hashCode() 오버라이딩 완료 상태
		
		while(lotto.size() < 6) {
			// lotto에 저장된 값이 6개 미만이면 반복
			
			int random = (int)(Math.random() * 45 + 1); // 1~ 45 사이 난수
			
			System.out.println(random); // 발생 순서 확인
			
			lotto.add(random);
			// int값이 자동으로 Integer로 포장(AutoBoxing)되어 lotto추가
			
		}
		
		System.out.println("로또 번호 : " + lotto);
		
	}
}
profile
Willingness to be a fool!

0개의 댓글