Set 컬렉션

오늘·2021년 4월 4일
0

Java

목록 보기
38/42

Set

List는 저장 순서를 유지하지만,
Set은 저장 순서가 유지되지 않는다

: 객체의 중복저장 불가
-> 동일 값, 동등 객체의 중복 저장 x
: 하나의 null은 저장 가능
: 순서가 유지되지 않기 때문에 인덱스로 꺼내올 수 없음. 그래서 사용하는 것이 이터레이터!

-Set은 인덱스로 관리하지 않기 때문에, 인덱스를 매개값으로 갖는 메소드가 없다.
-E라는 타입 파라미터는 Set이 인터페이스가 제네릭 타입이기 때문이다.

자료 값 입력은 .add / 삭제 .remove

다음은 set컬렉션에 객체를 추가 삭제하는 모습이다.

// Set에 자료 값 입력하기
// Integer 형식
set.add(10);
// String 형식
set.add("Java");
// boolean 형식
set.add(true);
// 객체(클래스)
set.add(new Student());

// 중복값을 넣으려 하면 오류는 안나지만 저장이 안된다
set.add(10);

// 값 삭제하기
set.remove(true);

객체 가져오기 Iterator

Iterator 인터페이스에 선언된 메소드는 아래와 같다

Set은 인덱스로 객체를 검색해서 가져오는 메소드가 없다. 대신, 전체 객체를 하나씩 가져오는 반복자(=Iterator)를 제공하는 것이다

// 반복자 메소드 호출
Iterator 변수명 = set객체명.iterator();

// 가져올 객체가 있을때까지 (true 리턴받아) 반복
// =저장된 객체 수만큼 반복한다
while(변수명.hasNext()) {
	System.out.println(변수명.next());
}

HashSet

Set 인터페이스의 구현 클래스

// 생성자 호출
Set<E> 변수명 = new HashSet<E>();

만약 문자열을 HashSet에 저장할 경우, 같은 문자열을 갖는 String 객체는 동등한 객체로 간주되고 다른 문자열을 갖는 String 객체는 다른 객체로 단주된다.

사용해보기 01

HashSet을 생성자 호출 해준 뒤 값을 입력해주고 .add
현재 사이즈를 확인 해본다 .size
자료를 하나씩 출력하기 위해 Iterator
값 지워주기 위해 .remove
저장된 객체를 모두 삭제하기 위해 .clear()

public class HashSetEx {
	public static void main(String[] args) {
		HashSet set = new HashSet();
		
		// Set에 자료 값 입력하기
		set.add(10);
		set.add("Java");
		set.add(true);
		set.add(new Student());
		// 중복값을 넣으려 하면 오류는 안나지만 저장이 안된다
		set.add(10);
		
		// 사이즈를 출력해보면 5개를 입력했음에도 4개만 저장되어있는 걸 확인
		// 왜냐면 중복값은 새로운 값으로 받아들이지 않기 때문에
		System.out.println("현재 set의 사이즈 : " + set.size());
		
		System.out.println();
		
		// 자료를 하나씩 출력하기
		// 입력 순서와 상관없이 값이 튀어나오는 모습을 볼 수 있다
		Iterator it = set.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
		
		System.out.println();
		
		// 값 지워주기
		set.remove(true);
		// 확인
		System.out.println("값 하나를 지워준 뒤 set의 사이즈 : " + set.size());
		Iterator it2 = set.iterator();
		while(it2.hasNext()) {
			System.out.println(it2.next());
		}

		
		
		System.out.println();
		
		// 저장된 객체 모두 삭제
		set.clear();
		System.out.println("clear한 후 set의 사이즈 : " + set.size());
	}
}


class Student{
	@Override
	public String toString() {
		return "Student 클래스";
	}
}

실행 모습

생성자 호출시 타입을 지정 안해줬기 때문에 다양한 값들이 들어갈 수 있었지만, 지정해주는 것이 좋다.

사용해보기 02

생성자 호출시 타입을 지정해서 사용하는 모습

Set<String> set = new HashSet<String>();
		
// 값 저장
// 중복 값 입력시 저장 되는지 확인
set.add("Java");
set.add("JDBC");
set.add("Servlet/JSP");
set.add("Java");
set.add("iBATIS");
		
// 저장된 객체 수 얻기
int size = set.size();
System.out.println("총 객체 수 : " + size);

// 반복자 얻기
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
	String element = iterator.next();
	System.out.println("\t" + element);
}
		
// 객체 삭제
set.remove("JDBC");
set.remove("iBATIS");
System.out.println("총 객체 수 : " + set.size());
iterator = set.iterator();
while(iterator.hasNext()) {
	String element = iterator.next();
	System.out.println("\t" + element);
}
		
// 객체 모두 삭제
set.clear();
if(set.isEmpty()) { 
	System.out.println("비어있습니다");
}

실행 결과

총 객체 수 : 4
	Java
	JDBC
	Servlet/JSP
	iBATIS
총 객체 수 : 2
	Java
	Servlet/JSP
비어있습니다

hashCode()와 equals()메소드를 재정의해 사용 01

인스턴스가 달라도 이름과 나이가 동일하다면, 동일 객체로 간주하여 중복 저장되지 않도록 하기 위해서..

// 클래스 멤버를 집어넣어 중복으로 set에 들어가는지 확인
public class HashSetEx2 {
	public static void main(String[] args) {
		// Set을 만드는데 리턴타입은 Member로 한다
		Set<Member> set = new HashSet<Member>();
		
		Member m1 = new Member("홍길동", 13, "123");
		Member m2 = new Member("김자바", 20, "312");
		Member m3 = new Member("이곡길", 25, "132");
		Member m4 = new Member("홍길동", 13, "123");
		
		set.add(m1);
		set.add(m2);
		set.add(m3);
		set.add(m4);
		
		// 주소를 받아들이고 있기 때문에
		// 동일 객체도 다른 값으로 판단
		// 그래서 Member에서 equals 처리를 해줘야 한다.
		System.out.println("set에 들어간 자료 개수 : " + set.size());
		
	
		System.out.println();
		System.out.println("[해쉬코드 값 출력]");
		// 해쉬코드 출력
		System.out.println(m1.hashCode());
		System.out.println(m2.hashCode());
		System.out.println(m3.hashCode());
		System.out.println(m4.hashCode());
		
		
		System.out.println();
		System.out.println("[equals 비교]");
		// equal 값 출력
		System.out.println(m1.equals(m2));
		System.out.println(m1.equals(m4));
		
	}
}

class Member {
	String name;
	String tel;
	int age;
	
	public Member(String name, int age, String tel) {
		this.name = name;
		this.age = age;
		this.tel = tel;
	}
	
	// 값이 다 같으면 동일한 hashCode를 리턴해준다
	@Override
	public int hashCode() {
		return name.hashCode() + age + tel.hashCode();
	}
	
	// name과 age값이 같이면 true를 리턴하는 곳
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Member) {
			Member member = (Member) obj;
			return member.name.equals(name) && (member.age == age) && member.tel.equals(tel);
		} else {
			return false;
		}
	}
}

실행 모습

hashCode()와 equals()메소드를 재정의해 사용 02

  • 요구사항
 학생 객체
 1반 1번 100
 1반 2번 89
 1반 2번 90
 1반 1번 80
 
 출력
 1반 1번 180점
 1반 2번 179점

전체 코드

public class HashSetEx_Test {
	public static void main(String[] args) {
		Set<Student1> set = new HashSet<Student1>();

		Student1 s1 = new Student1(1, 1, 100);
		Student1 s2 = new Student1(1, 2, 89);
		Student1 s3 = new Student1(1, 2, 90);
		Student1 s4 = new Student1(1, 1, 80);

		if (s1.equals(s2)) {
			s1.hap = s1.hap + s1.jumsu + s2.jumsu;
		}
		if (s1.equals(s3)) {
			s1.hap = s1.hap + s1.jumsu + s3.jumsu;
		}
		if (s1.equals(s4)) {
			s1.hap = s1.hap + s1.jumsu + s4.jumsu;
		}
		if (s2.equals(s3)) {
			s2.hap = s2.hap + s2.jumsu + s3.jumsu;
		}
		if (s2.equals(s4)) {
			s2.hap = s2.hap + s2.jumsu + s4.jumsu;
		}
		if (s3.equals(s4)) {
			s3.hap = s3.hap + s3.jumsu + s4.jumsu;
		}

		set.add(s1);
		set.add(s2);
		set.add(s3);
		set.add(s4);

		Iterator<Student1> it = set.iterator();
		while (it.hasNext()) {
			Student1 s = it.next();
			System.out.println(s.ban + "반  " + s.bun + "번 " + s.hap + "점 ");
		}
	}
}

class Student1 {
	int ban;
	int bun;
	int jumsu;
	int hap;

	public Student1(int ban, int bun, int jumsu) {
		this.ban = ban;
		this.bun = bun;
		this.jumsu = jumsu;
	}

	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return ban + bun;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Student1) {
			Student1 s = (Student1) obj;
			if (ban == s.ban && bun == s.bun)
				return true;

		}
		return false;
	}
}

실행 모습

1반  1번 180점 
1반  2번 179점 

0개의 댓글