IT 면접족보/자바 면접족보

자바 수업 정리 -컬렉션 클래스- ArrayListE&LinkedListE, SetE&HashSetE(21 일차)

낙산암 2020. 12. 23. 17:14

1. ArrayList 와 LinkedList 의 장단점은?

 

상황마다 적절한 자료 구조가 다르기 때문에 각각의 장단점을 잘 파악해 두고 프로그램을 짜기 전에 어떤 것을 사용해야 할지 꼭 미리 생각해보고 사용하자.

 

2. Scanner 클래스로 -1이 입력될 때까지 양의 정수를 입력 받아 저장하고 검색하여 가장 큰 수를 출력하는 프로그램을 작성하라.

정수(-1이 입력될 때까지)>> 10 6 22 6 88 77 -1
가장 큰 수는 88
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class PositiveNumberPrint {
	public static void main(String[] args) {
	
		Scanner sc = new Scanner(System.in);
		System.out.println("정수(-1이 입력될 때까지)>>");
		
		List<Integer> list = new LinkedList<>();
		
		int num = 0;
		while(num != -1) {
			num = sc.nextInt();
			list.add(num);
		}
		sc.close();
		
		int maxNum = 0;
		for(int i=0; i<list.size(); i++) {
			if(list.get(i) > maxNum) {
				maxNum = list.get(i);
			}
		}
		System.out.println("가장 큰 수는 " + maxNum);
		
		// 더욱 간결한 방법이 있나 찾아보다가 알게된 방법 
//		System.out.println("가장 큰 수는 " + Collections.max(list));
	}
}

3. 로또 프로그램을 작성하시오.(Set 으로)

생각해볼 점! 수업시간에 연습할 때 소스 코드는 엄청 길게 나왔다. 불필요한 부분이 많았던 것 같다. 프로그램을 짜고 나서도, 더 간결하고 좋은 코드가 있는지, 불필요한 부분이 있는지 개선점을 꼭 생각해보자!

 

import java.util.HashSet;
import java.util.Set;

public class LottoTeacher {
	public static void main(String[] args) {
		Set<Integer> set = new HashSet<Integer>(); 
		
		while(set.size() < 6) {  //종결 조건 여기에 바로 넣으면 간결 
			set.add((int)(Math.random()*45)+1); //여기도 set함수에 바로 넣으면 간결! 
		}
		System.out.println(set);  //바로 출력 된다! 
	}
}

4. Set에 대하여 설명하시오.

집합의 개념을 구현해 놓은 것이 set이다. (수학으로 set 집합)

Set<E> 인터페이스를 구현하는 제네릭 클래스이 갖는 중요한 특징!

  • 저장 순서가 유지 되지 않는다.
  • 데이터의 중복 저장을 허용하지 않는다. = set을 사용하면 중복 체크를 할 필요가 없다.

collection interface는 Iterable interface 상속하므로 iterator 반복자 호출해서 사용할 수 있다. (set, list queue 동일)

 

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

public class SetEx {

	public static void main(String[] args) {
		Set<String> set = new HashSet<>();
		set.add("Toy"); 	set.add("Box");
		set.add("Robot"); 	set.add("Box");
		System.out.println("인스턴스 수: " + set.size());
		
		//반복자를 이용한 전체 출력 
		for(Iterator<String> itr= set.iterator(); itr.hasNext(); )
			System.out.print(itr.next() + '\t');
		System.out.println();
		
		//for-each문을 이용한 전체 출력 
		for(String s : set)
			System.out.print(s + '\t');
		System.out.println();
	}
}

6. 프로그래밍

Scanner 클래스를 사용하여 6개 학점('A', 'B', 'C', 'D', 'F')을 문자로 입력받아 ArrayList에 저장하고, ArrayList를 검색하여 학점을 점수(A=4.0, B=3.0, C=2.0, D=1.0, F=0)로 변환하여 평균을 출력하는 프로그램을 작성하라.

 

6개의 학점을 빈 칸으로 분리 입력(A/B/C/D/F) >> A C A B F D 2.3333333333333335

 

public class Main {
    public static void main(String[] args) {
    	Grade grade = new Grade();
    	grade.inputGrade();
    	System.out.println(grade.getAverage());
    	
    }
}

class Grade {
	private ArrayList<String> grade;
	
	public Grade() {
		grade = new ArrayList<String>();
	}
	
	public void inputGrade() {
		Scanner scanner = new Scanner(System.in);
		System.out.print("6개의 학점을 빈 칸으로 분리 입력(A/B/C/D/F) >> ");
		while(grade.size() < 6) {
			grade.add(scanner.next());
		}
	}
	
	public double getAverage() {
		double avg;
		double sum = 0;
		
		for(String e : grade) {
			switch(e) {
			case "A" :
				sum += 4.0;
				break;
			case "B" :
				sum += 3.0;
				break;
			case "C" :
				sum += 2.0;
				break;
			case "D" :
				sum += 1.0;
				break;
			}
		}
		avg = sum / 6;
		return avg;
	}
}

7. 출력이 아래와 같이 나오도록 하시오(필수) ⭐️

		HashSet<Num> set = new HashSet<>();
        set.add(new Num(7799));
        set.add(new Num(9955));
        set.add(new Num(7799));

        System.out.println("인스턴스 수: " + set.size());

        for(Num n : set)
            System.out.print(n.toString() + '\t');

        System.out.println();

/*
====출력
인스턴스 수: 2
7799	9955
*/
class Num {
	int num;
	
	Num(int num) {
		this.num = num;
	}
	
	@Override
	public String toString() {
		return String.valueOf(num);
	}
	
	@Override
	public int hashCode() {
		return num % 2;  //출력 순서를 맞추려면 이렇게 변경하면 된다는것까지 알았는데 정확히 왜인지는 모르겠다.
	}
	
	@Override
	public boolean equals(Object obj) {
		if(this.num == ((Num)obj).num)
			return true;
		else 
			return false;
	}
}

public class HashNum {

	public static void main(String[] args) {
		HashSet<Num> set = new HashSet<>();
		set.add(new Num(7799));
		set.add(new Num(9955));
		set.add(new Num(7799));

		System.out.println("인스턴스 수: " + set.size());

		for (Num n : set)
			System.out.print(n.toString() + '\t');

		System.out.println();
	}
}

/*
인스턴스 수: 2
7799	9955
*/

8. Set 호출되는 원리와 순서를 설명하시오.

앞서 보았듯 set은 집합을 구현한 것으로 저장 순서가 유지되지 않고, 데이터의 중복 저장을 허용하지 않는다. 이를 구현하기 위해서는 동일 인스턴스가 중복 저장되지 않도록 해야한다. 그러므로 set을 호출하기 위해서 다음 두 개가 호출되어야 한다는 것을 반드시 이해해야 한다. 아래의 두 개가 다 같아야 동일 인스턴스이다.

해시알고리즘은 동일인스턴스가 있는지 검사를 하기위한 속도를 획기적으로 향상시킬 수 있는 방법!

1. hash code 호출 (두 개 객체 주소-hash code가 같은지 비교)

hashCode 는 Object에 있다. 아래의 예시와 같이 오버라이드 한 함수를 통과해 리턴 되는 값으로 군집(집합, 캐비넷)을 만든다. 그리고 그 다음 equals를 호출한다.

 

1. hash code 호출 (두 개 객체 주소-hash code가 같은지 비교)

hashCode 는 Object에 있다. 아래의 예시와 같이 오버라이드 한 함수를 통과해 리턴 되는 값으로 군집(집합, 캐비넷)을 만든다. 그리고 그 다음 equals를 호출한다.

2. equals 호출 (문자열 비교 걸러냄)

hash code의 호출로 군집히 형성되면 그 군집 내의 요소들을 비교해 나간다.

다음 예시는 값을 비교하기 위해 오버라이드 한 것이다.

 

Set 호출에는 2단계를 거쳐 진행된다.

  1. 클래스에 정의된 hashCode 메소드의 반환 값을 통해 분류.

  2. 선택된 부류 내에서 equals 메소드를 호출하여 비교.

따라서 Set은 hashCode를 기반으로 분류된 데이터 속에서 탐색을 하면 되기 때문에 탐색속도가 높다.

 

9. 아래와 같이 출력되도록 하시오.

HashSet<Person> hSet = new HashSet<Person>();
hSet.add(new Person("LEE", 10));
hSet.add(new Person("LEE", 10));
hSet.add(new Person("PARK", 35));
hSet.add(new Person("PARK", 35));

System.onut.println("저장된 데이터 수: " + hSet.size());
System.out.println(hSet);

/*
============
저장된 데이터 수: 2
[LEE(10세), PARK(35세)]
*/
class Person {
	private String name;
	private int age;
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	@Override
	public int hashCode() {
		return age;
	}
	
	@Override
	public boolean equals(Object obj) {
		if(name.equals(((Person) obj).name) && age == ((Person) obj).age)
			return true;
		else
			return false;
	}
	
	@Override
	public String toString() {
		return name + "(" + age + "세)";
	}
}