본문 바로가기

Java 웹 개발

21.09.09 - 웹 개발 입문 22일차

Q . 달력 만들기
연도와 월 정보를 사용자가 입력하면 해당 정보를 이용하여 달력을 구현
첫 줄에는 `일` 부터 `토` 까지 요일을 출력하고 그 다음줄부터는 숫자가 나오는 달력을 구현
달력의 시작지점은 전 달의 특정 일자부터일 수 있으며, 날짜는 총 7개씩 6줄에 걸쳐서 42번 출력해야함.
따라서 마지막에는 다음달의 특정 일자가 나올 수 있다. 

ex)
연도 입력 : 2021
월 입력 : 9


<2021년 9월 달력>

수 
29 30 31 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 1 2
3 4 5 6 7 8 9



- 1. 달력 모양 구현 하기

package api.util.calendar;

public class Test04 {
	public static void main(String[] args) {

		// 입력
		int year = 2021;
		int month = 9;

		// 출력
		System.out.print("<");
		System.out.print(year);
		System.out.print("년");
		System.out.print(" ");
		System.out.print(month);
		System.out.print("월");
		System.out.print(">");
		System.out.println("\n");

		System.out.println("일\t월\t화\t수\t목\t금\t토\n");

		for (int i = 0; i < 6; i++) {
			for (int k = 0; k < 7; k++) {
				System.out.print("?");
				System.out.print("\t");
			}
			System.out.println();
			System.out.println();
		}

	}
}

 

 

2. 계산
- 입력값에 있는 연도와 월, 1일로 달력을 설정
- 해당 월의 1일의 요일을 계산
- 위에서 계산한 날짜 바로 직전의 일요일 날짜를 구해야 한다 (달력은 일요일부터 출력되기 때문)

package api.util.calendar;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class Test04_1 {
	public static void main(String[] args) {

		// 입력
		int year = 2021;
		int month = 9;

		// 1
		Calendar c = Calendar.getInstance();

		// 2
		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, month - 1);// 주의 : 월은 0~11로 관리되므로 1 작게 넣어야 한다
		c.set(Calendar.DATE, 1);

		// 3
		int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
		System.out.println("요일 = " + dayOfWeek);

		// 4
		int beforeDays = dayOfWeek - 1;// 뒤로 이동해야할 날짜
		c.add(Calendar.DATE, -beforeDays);

		// 출력
		for (int i = 0; i < 42; i++) {
			Format f = new SimpleDateFormat("y년 M월 d일 E");
			System.out.println(f.format(c.getTime()));

			c.add(Calendar.DATE, 1);// 다음날로 설정
		}
	}
}

 

 

3. 마지막 합치기

package api.util.calendar;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Scanner;

public class Test04_2 {
	public static void main(String[] args) {

		//입력
        //1
		Calendar c = Calendar.getInstance();
        
        Scanner sc = new Scanner(System.in);
        
		System.out.print("연도 입력 : ");
		int year = sc.nextInt();

		System.out.print("월 입력 : ");
		int month = sc.nextInt();

		sc.close();
        
		//2
		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, month-1);//주의 : 월은 0~11로 관리되므로 1 작게 넣어야 한다
		c.set(Calendar.DATE, 1);

		//3
		int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
		System.out.println("요일 = " +dayOfWeek);

		//4
		int beforeDays = dayOfWeek - 1;//뒤로 이동해야할 날짜
		c.add(Calendar.DATE, -beforeDays);

		//출력

		System.out.print("<");
		System.out.print(year);
		System.out.print("년");
		System.out.print(" ");
		System.out.print(month);
		System.out.print("월");
		System.out.print(">");
		System.out.println("\n");

		System.out.println("일\t월\t화\t수\t목\t금\t토\n");

		for(int i=0; i < 6; i++) {
			for(int k=0; k < 7; k++) {
				System.out.print(c.get(Calendar.DATE));
				System.out.print("\t");

				c.add(Calendar.DATE, 1);
			}
			System.out.println();
			System.out.println();
		}

	}
}

- 정답

 

---> 추가 >연도와 월을 이용하여 달력을 출력하는 클래스

package api.util.calendar;

import java.util.Calendar;


public class KCalendar {
	private Calendar c = Calendar.getInstance();

	public void setYear(int year) {
		this.c.set(Calendar.YEAR, year);
	}

	public void setMonth(int month) {
		if (month < 1 || month > 12) {
			return;
		}
		this.c.set(Calendar.MONTH, month - 1);
	}

	public int getYear() {
		return this.c.get(Calendar.YEAR);
	}

	public int getMonth() {
		return this.c.get(Calendar.MONTH) + 1;
	}

	public int getDay() {
		return this.c.get(Calendar.DATE);
	}

	public void prev() {
		this.c.add(Calendar.DATE, -1);
	}

	public void prev(int size) {
		this.c.add(Calendar.DATE, -size);
	}

	public void next() {
		this.c.add(Calendar.DATE, 1);
	}

	public void next(int size) {
		this.c.add(Calendar.DATE, size);
	}

	public KCalendar(int year, int month) {
		this.setYear(year);
		this.setMonth(month);
	}

	public void print() {
		int year = this.getYear();
		int month = this.getMonth();

		c.set(Calendar.DATE, 1);

		int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);

		int beforeDays = dayOfWeek - 1;// 뒤로 이동해야할 날짜
		// c.add(Calendar.DATE, -beforeDays);
		this.prev(beforeDays);

		// 출력
		System.out.print("<");
		System.out.print(year);
		System.out.print("년");
		System.out.print(" ");
		System.out.print(month);
		System.out.print("월");
		System.out.print(">");
		System.out.println("\n");

		System.out.println("일\t월\t화\t수\t목\t금\t토\n");

		for (int i = 0; i < 6; i++) {
			for (int k = 0; k < 7; k++) {
				System.out.print(this.getDay());
				System.out.print("\t");

				this.next();// c.add(Calendar.DATE, 1);
			}
			System.out.println();
			System.out.println();
		}
	}
}
package api.util.calendar;

public class Test04_3 {
	public static void main(String[] args) {
		KCalendar calendar = new KCalendar(2021, 9);
		calendar.print();
	}
}

 

 

 

 

라이브러리 - Random 클래스

 

- 기본적인 랜덤 클래스 구현 방식

package api.util.random;

import java.util.Random;

public class Test01 {
	public static void main(String[] args) {

		Random r = new Random();

		int dice = r.nextInt(6) + 1;
		System.out.println("dice = " + dice);

		System.out.println(r.nextInt());// 무작위 int 범위 내에서의 값 1개 반환
		System.out.println(r.nextBoolean());
		System.out.println(r.nextLong());
		System.out.println(r.nextFloat());
		System.out.println(r.nextDouble());
		System.out.println(r.nextGaussian());// 정규분포
	}
}

 

 

 

- 시드(SEED)란 무엇인가?
랜덤값을 만들어내기 위한 계산의 시작값을 시드라 함

package api.util.random;

import java.util.Random;

public class Test02 {
	public static void main(String[] args) {

		Random r = new Random();

		r.setSeed(1L);
		int a = r.nextInt();
		r.setSeed(1L);
		int b = r.nextInt();

		System.out.println("a = " + a);
		System.out.println("b = " + b);
	}
}

a = -1155869325
b = -1155869325

값이 똑같아진다

 

 

- 시드를 통해 OTP 원리 구현 해보기

OTP(One Time Password, 일회용 비밀번호)
비밀번호는 이를 이용하는 고객과 이를 확인하는 프로그램이 존재해야 한다.
즉 2명 이상이 일정 시간동안 "동일한 랜덤번호"를 알고 있어야 성립될 수 있다.

 

- 랜덤 번호 설정

package api.util.random;

import java.util.Random;

public class Test03 {
	public static void main(String[] args) throws InterruptedException {

		Random r = new Random();

		while(true) {
			int otp = r.nextInt(1000000);
			System.out.println("otp = " + otp);

			Thread.sleep(100L);
		}
	}
}

 

 

 

- 시드를 동일하게 설정하여 계속 같은 번호가 나오도록 구현

package api.util.random;

import java.util.Random;

public class Test03_1 {
	public static void main(String[] args) throws InterruptedException {

		Random r = new Random();

		while(true) {
			r.setSeed(1L);

			int otp = r.nextInt(1000000);
			System.out.println("otp = " + otp);

			Thread.sleep(100L);
		}
	}
}

 

 

- 일정시간 동안 동일한 값이 나오게 시간 정보를 조작

package api.util.random;

import java.util.Random;

public class Test03_2 {
	public static void main(String[] args) throws InterruptedException {
		
		while(true) {
//			long time = System.currentTimeMillis();
//			long time = System.currentTimeMillis() / 1000;//1초마다 바뀜
//			long time = System.currentTimeMillis() / 1000 / 10;//10초마다 바뀜
//			long time = System.currentTimeMillis() / 1000 / 60;//60초마다 바뀜
			long time = System.currentTimeMillis() / 1000 / 72;//72초마다 바뀜
			System.out.println("time = " + time);
		}
	}
}

 

 

- 앞에서 계산한 시간을 SEED로 사용하여 랜덤값을 추출

package api.util.random;

import java.util.Random;

public class Test03_3 {
	public static void main(String[] args) throws InterruptedException {
    
		Random r = new Random();
		while(true) {
        
			long time = System.currentTimeMillis() / 1000;//1초마다 바뀜

			r.setSeed(time);
			int otp = r.nextInt(1000000);
			System.out.println("OTP : "+otp);
		}
	}
}

 

 

- 자리수 맞추는법

Format 클래스 중에 DecimalFormat 클래스를 이용하여 숫자 형식을 재설정
# 은 숫자가 있는 경우만 출력(자리수 보전 불가)
0 은 숫자가 없으면 0으로 출력(자리수 보전 가능)

package api.util.random;

import java.text.DecimalFormat;
import java.text.Format;

public class Test03_4 {
	public static void main(String[] args) throws InterruptedException {

		int a = 1234567890;
		System.out.println("a = " + a);

		Format f1 = new DecimalFormat("#,###");
		System.out.println("a = " + f1.format(a));

		int b = 10;
		System.out.println("b = " + b);
		System.out.println("b = " + f1.format(b));

		Format f2 = new DecimalFormat("0,000");
		System.out.println("a = " + f2.format(a));
		System.out.println("b = " + f2.format(b));

		Format f3 = new DecimalFormat("#,##0.00");
		System.out.println("b = " + f3.format(b));

		double c = 0.567;
		System.out.println("c = " + c);
		System.out.println("c = " + f3.format(c));

	}
}

 

 

- DecimalFormat을 적용시켜 무조건 6자리로 표현되도록 구현
식 : 000000

package api.util.random;

import java.text.DecimalFormat;
import java.text.Format;
import java.util.Random;

public class Test03_5 {
	public static void main(String[] args) throws InterruptedException {

		Random r = new Random();
		Format f = new DecimalFormat("000000");

		while(true) {
			long time = System.currentTimeMillis() / 1000;//1초마다 바뀜
//			long time = System.currentTimeMillis() / 1000 / 10;//10초마다 바뀜
//			long time = System.currentTimeMillis() / 1000 / 60;//60초마다 바뀜
//			long time = System.currentTimeMillis() / 1000 / 72;//72초마다 바뀜

			r.setSeed(time);
			int otp = r.nextInt(1000000);
			System.out.println("OTP : "+f.format(otp));
		}
	}
}

 

 

-서로 다른 사용자가 다른 값이 나오게 하려면 "시간" 외에 "사용자별 고유정보"를 추가하여 시드를 생성

package api.util.random;

import java.text.DecimalFormat;
import java.text.Format;
import java.util.Random;

public class Test03_6 {
	public static void main(String[] args) throws InterruptedException {

		String a = "frist";
		String b = "second";

		Random r = new Random();
		Format f = new DecimalFormat("000000");

		while(true) {
			long time = System.currentTimeMillis() / 1000;//1초마다 바뀜
//			long time = System.currentTimeMillis() / 1000 / 10;//10초마다 바뀜
//			long time = System.currentTimeMillis() / 1000 / 60;//60초마다 바뀜
//			long time = System.currentTimeMillis() / 1000 / 72;//72초마다 바뀜

			r.setSeed(time + a.hashCode());
			int otpA = r.nextInt(1000000);
			System.out.print("[A사용자] OTP : "+f.format(otpA));

			r.setSeed(time + b.hashCode());
			int otpB = r.nextInt(1000000);
			System.out.print(", [B사용자] OTP : "+f.format(otpB));
			System.out.println();

			Thread.sleep(100L);
		}
	}
}

- 정답

[A사용자] OTP : 164314, [B사용자] OTP : 480352
[A사용자] OTP : 164314, [B사용자] OTP : 480352
[A사용자] OTP : 164314, [B사용자] OTP : 480352
[A사용자] OTP : 164314, [B사용자] OTP : 480352
[A사용자] OTP : 971939, [B사용자] OTP : 287978
[A사용자] OTP : 971939, [B사용자] OTP : 287978
[A사용자] OTP : 971939, [B사용자] OTP : 287978
[A사용자] OTP : 971939, [B사용자] OTP : 287978
[A사용자] OTP : 971939, [B사용자] OTP : 287978
[A사용자] OTP : 971939, [B사용자] OTP : 287978
[A사용자] OTP : 971939, [B사용자] OTP : 287978
[A사용자] OTP : 971939, [B사용자] OTP : 287978
[A사용자] OTP : 971939, [B사용자] OTP : 287978
[A사용자] OTP : 549063, [B사용자] OTP : 326105

 

 

 

 

라이브러리 - Arrays 클래스

 

Arrays 클래스 : 배열에 대한 처리를 도와주는 클래스

package api.util.arrays;

import java.util.Arrays;

public class Test01 {
	public static void main(String[] args) {

		int[] arr = new int[] {30, 50, 20, 10, 40};

//		출력
		System.out.println(Arrays.toString(arr));

//		채우기
		Arrays.fill(arr, 0);

		System.out.println(Arrays.toString(arr));

	}
}

 

- 위치 찾기

package api.util.arrays;

import java.util.Arrays;

public class Test02 {
	public static void main(String[] args) {

		int[] arr = new int[] { 30, 50, 20, 10, 40 };

//		20은 몇 번째 위치에 있습니까?
		int index = Arrays.binarySearch(arr, 210);
		System.out.println("index = " + index);
		if (index >= 0) {
			System.out.println("있어요");
		} else {
			System.out.println("없어요");
		}

	}
}

 

 

- Arrays를 이용한 정렬(sort)

원시형은 정렬의 방식을 커스터마이징 할 수 없다 (int -> Integer로 변경)

package api.util.arrays;

import java.util.Arrays;
import java.util.Comparator;

public class Test03 {
	public static void main(String[] args) {

		Integer[] data = new Integer[] { 30, 50, 20, 10, 40 };

//		Arrays.sort(data);//전체 오름차순 정렬
//		Arrays.sort(data, 1, 3);//부분 오름차순 정렬(1부터 3 전까지)

//		generic type에는 참조형만 작성할 수 있다.(int를 쓰고 싶다면 Integer라고 작성해야 한다)
		Comparator<Integer> c = new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				// (+는 순서교체, 0은 동일, -는 현상유지를 의미)
				// o1이 앞쪽에 있는 데이터, o2가 뒤쪽에 있는 데이터
				// = 오름차순이 되려면 앞에 있는 데이터(o1)가 뒤에 있는 데이터(o2)보다 작아야 합니다
				// = 내림차순이 되려면 앞에 있는 데이터(o1)가 뒤에 있는 데이터(o2)보다 커야 합니다

				/*
				if(o1 < o2) {//앞이 작으면
					return 1;//바꾸세요
				}
				else if(o1 > o2) {//앞이 크면
					return -1;//놔두세요
				}
				else {//같으면
					return 0;//같아요
				}
				*/
				return o2 - o1; // 한번에 표시
				
			}
		};
		Arrays.sort(data, c);// data라는 배열을 c라는 비교기준에 의해서 정렬해라!

		System.out.println(Arrays.toString(data));
	}
}

 

- 정리

package api.util.arrays;

import java.util.Arrays;
import java.util.Comparator;

public class Test03_1 {
	public static void main(String[] args) {
		Integer[] data = new Integer[] {30, 50, 20, 10, 40};

		Comparator<Integer> c = new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o2 - o1;
			}
		};
		Arrays.sort(data, c);

		System.out.println(Arrays.toString(data));
	}
}

 

- 람다(Lambda) 표현식 으로 정리
추상메소드가 하나뿐인 인터페이스라면 간단한 정보만 알려주고 나머지는 추리하도록 지시 가능
추상 클래스는 안됩니다

package api.util.arrays;

import java.util.Arrays;
import java.util.Comparator;

public class Test03_2 {
	public static void main(String[] args) {
		Integer[] data = new Integer[] {30, 50, 20, 10, 40};

		Comparator<Integer> c = (o1, o2) -> {
			return o2 - o1;
		};
		Arrays.sort(data, c);

		System.out.println(Arrays.toString(data));
	}
}

-> Comparator<Integer> c = (o1, o2) -> o1 - o2; 까지 최종적으로 줄일 수 있다.

- 정답

[10, 20, 30, 40, 50]

 

 

Arrays 정렬

Q. data를 "내림차순" 정렬해서 화면에 출력해보세요
참고하실 명령은 String class의 compareTo() 입니다.

package api.util.arrays;

import java.util.Arrays;

public class Test04 {
	public static void main(String[] args) {

		String[] data = new String[] {"피카츄", "라이츄", "파이리", "꼬부기", "버터플"};

		Arrays.sort(data);

		System.out.println(Arrays.toString(data));

	}
}

 

 

- 문자열의 크기라는 개념은 존재하지 않지만, 실생활에서는 가나다순으로 크기가 정해진다고 본다
문자열간의 차를 구해야 한다면, 글자와 연결된 값이 얼마인지를 계산하여 뺄셈을 수행한다

(1)

package api.util.arrays;

import java.util.Arrays;

public class Test04_1 {
	public static void main(String[] args) {

		String a = "피카츄";
		String b = "라이츄";
        
		char a1 = a.charAt(0);
		char b1 = b.charAt(0);
		System.out.println("a1 = " + a1 + "(" + (int)a1 + ")");
		System.out.println("b1 = " + b1 + "(" + (int)b1 + ")");
		System.out.println(b1 - a1);

		System.out.println(b.compareTo(a));

	}
}

a1 = 피(54588)
b1 = 라(46972)
-7616
-7616

 

(2)

package api.util.arrays;

import java.util.Arrays;

public class Test04_2 {
	public static void main(String[] args) {

		String a = "피카츄";
		String b = "피아노";

		char a1 = a.charAt(0);
		char b1 = b.charAt(0);
		System.out.println("a1 = " + a1 + "(" + (int)a1 + ")");
		System.out.println("b1 = " + b1 + "(" + (int)b1 + ")");
		System.out.println(b1 - a1);

		char a2 = a.charAt(1);
		char b2 = b.charAt(1);
		System.out.println("a2 = " + a2 + "(" + (int)a2 + ")");
		System.out.println("b2 = " + b2 + "(" + (int)b2 + ")");
		System.out.println(b2 - a2);

		System.out.println(b.compareTo(a));

	}
}

a1 = 피(54588)
b1 = 피(54588)
0
a2 = 카(52852)
b2 = 아(50500)
-2352
-2352

 

(3)

package api.util.arrays;

import java.util.Arrays;

public class Test04_3 {
	public static void main(String[] args) {

		String a = "피카츄";
		String b = "피아노";

		for(int i=0; i < Math.min(a.length(), b.length()); i++) {
			char partA = a.charAt(i);
			char partB = b.charAt(i);
			if(partA != partB) {
				System.out.println(partB - partA);
				break;
			}
		}

		System.out.println(b.compareTo(a));//b - a

	}
}

-2352
-2352

 

 

- 결론

package api.util.arrays;

import java.util.Arrays;
import java.util.Comparator;

public class Test04_4 {
	public static void main(String[] args) {

		String[] data = new String[] {"피카츄", "라이츄", "파이리", "꼬부기", "버터플"};
        .
		Comparator<String> c  = new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				if(o1.compareTo(o2) < 0) {
					return 1;
				}
				else if(o1.equals(o2)) {
					return 0;
				}
				else {
					return -1;
				}
			}
		};
		Arrays.sort(data, c);

		System.out.println(Arrays.toString(data));

	}
}

 

- 정리 (1)

package api.util.arrays;

import java.util.Arrays;
import java.util.Comparator;

public class Test04_5 {
	public static void main(String[] args) {

		String[] data = new String[] {"피카츄", "라이츄", "파이리", "꼬부기", "버터플"};

		Comparator<String> c  = new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o2.compareTo(o1);//o2 - o1
			}
		};
		Arrays.sort(data, c);

		System.out.println(Arrays.toString(data));

	}
}

 

정리 (2)

package api.util.arrays;

import java.util.Arrays;
import java.util.Comparator;

public class Test04_6 {
	public static void main(String[] args) {

		String[] data = new String[] {"피카츄", "라이츄", "파이리", "꼬부기", "버터플"};

		Comparator<String> c  = (o1, o2) -> {
			return o2.compareTo(o1);//o2 - o1
		};
		Arrays.sort(data, c);

		System.out.println(Arrays.toString(data));

	}
}

 

- 최종 정리

package api.util.arrays;

import java.util.Arrays;
import java.util.Comparator;

public class Test04_7 {
	public static void main(String[] args) {

		String[] data = new String[] { "피카츄", "라이츄", "파이리", "꼬부기", "버터플" };

		Comparator<String> c = (o1, o2) -> o2.compareTo(o1);// o2 - o1
		Arrays.sort(data, c);

		System.out.println(Arrays.toString(data));

	}
}

- 정답

[피카츄, 파이리, 버터플, 라이츄, 꼬부기]

 

 

 

Q : 객체 배열을 정렬하려면?

 

1. 객체 클래스 생성

package api.util.arrays;

public class Student implements Comparable<Student>{
	private String name;
	private int score;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	public Student(String name, int score) {
		super();
		this.name = name;
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", score=" + score + "]";
	}
}

 

2. 객체 배열 생성

package api.util.arrays;

import java.util.Arrays;
import java.util.Comparator;

public class Test05 {
	public static void main(String[] args) {
	
		Student[] list = new Student[3];

		list[0] = new Student("피카츄", 90);
		list[1] = new Student("라이츄", 75);
		list[2] = new Student("꼬부기", 80);

		// 학생(Student) 비교 기준
		// 1차 기준 : 이름 오름차순
		// 2차 기준 : 점수 내림차순
		Comparator<Student> c = new Comparator<Student>() {
			@Override
			public int compare(Student o1, Student o2) {

//				return o1이름 - o2이름;//이름 오름차순
//				return o2이름 - o1이름;//이름 내림차순
//				return o1점수 - o2점수;//점수 오름차순
//				return o2점수 - o1점수;//점수 내림차순

//				if(이름이 같으면) {
//					return o2점수 - o1점수;//점수 내림차순
//				}
//				else {
//					return o1이름 - o2이름;//이름 오름차순
//				}

				if (o1.getName().equals(o2.getName())) {
					return o2.getScore() - o1.getScore();
				} else {
//					return o1.getName() - o2.getName();
					return o1.getName().compareTo(o2.getName());
				}

			}
		};

		Arrays.sort(list, c);

		for (int i = 0; i < list.length; i++) {
			System.out.println("[" + i + "] " + list[i]);
		}
	}
}

 

- 정리

package api.util.arrays;

import java.util.Arrays;
import java.util.Comparator;

public class Test05_2 {
	public static void main(String[] args) {
		// Q : 객체 배열을 정렬하려면?
		Student[] list = new Student[3];

		list[0] = new Student("피카츄", 90);
		list[1] = new Student("라이츄", 75);
		list[2] = new Student("꼬부기", 80);

		// 학생(Student) 비교 기준
		// 1차 기준 : 이름 오름차순
		// 2차 기준 : 점수 내림차순
		Comparator<Student> c = (o1, o2) -> {
			if (o1.getName().equals(o2.getName())) {
				return o2.getScore() - o1.getScore();
			} else {
				return o1.getName().compareTo(o2.getName());
			}
		};

		Arrays.sort(list, c);

		for (int i = 0; i < list.length; i++) {
			System.out.println("[" + i + "] " + list[i]);
		}
	}
}

 

 

- 객체 클래스 추가

비교 기준을 클래스에 내장시킬 수 있다.
java.lang.Comparable 인터페이스를 상속받고 compareTo 메소드를 재정의

package api.util.arrays;

public class Student implements Comparable<Student>{
	private String name;
	private int score;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	public Student(String name, int score) {
		super();
		this.name = name;
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", score=" + score + "]";
	}

	@Override
	public int compareTo(Student o) {
		//o1 == this , o2 == o
		if(this.getName().equals(o.getName())) {
			return o.getScore() - this.getScore();
		}
		else {
			return this.getName().compareTo(o.getName());
		}
	}
}

 

- 최종 정리

package api.util.arrays;

import java.util.Arrays;
import java.util.Comparator;

public class Test05_4 {
	public static void main(String[] args) {
		//Q : 객체 배열을 정렬하려면?
		Student[] list = new Student[3];

		list[0] = new Student("피카츄", 90);
		list[1] = new Student("라이츄", 75);
		list[2] = new Student("꼬부기", 80);

		//비교기준이 정의된 클래스라면 따로 언급 없이도 정렬이 가능
		Arrays.sort(list);

		for(int i=0; i < list.length; i++) {
			System.out.println("["+i+"] " + list[i]);
		}
	}
}

- 정답

[0] Student [name=꼬부기, score=80]
[1] Student [name=라이츄, score=75]
[2] Student [name=피카츄, score=90]

 

 

 

라이브러리 - Scanner 기본 사용법

Scanner : 입력 클래스
원래 개발 목적이 키보드 입력용이 아니고 문자열 분해도구
키보드 입력용으로 쓰다 보니까 편하고 좋아서 모든 교재에서 이를 채택해서 사용할 뿐

package api.util.scanner;

import java.util.Scanner;

public class Test01 {
	public static void main(String[] args) {

		String song = "떳다떳다 비행기 날아라 날아라\n떳다떳다 비행기 우리비행기";
		System.out.println(song);

		// .hasNext() 더 읽을 내용이 있는지 판정하는 명령
		// .next() 공백 이전까지를 읽어들이는 명령(공백은 버림)
		Scanner sc = new Scanner(song);
		while (sc.hasNext()) {
			System.out.println(sc.next());
		}
		sc.close();
	}
}

떳다떳다 비행기 날아라 날아라
떳다떳다 비행기 우리비행기
떳다떳다
비행기
날아라
날아라
떳다떳다
비행기
우리비행기

 

 

- hasNext() , next() 차이 

.hasNext() 더 읽을 내용이 있는지 판정하는 명령
.next() 공백 이전까지를 읽어들이는 명령

package api.util.scanner;

import java.util.Scanner;

public class Test02 {
	public static void main(String[] args) {

		String song = "떳다떳다 비행기 날아라 날아라\n떳다떳다 비행기 우리비행기";
		System.out.println(song);

		Scanner sc = new Scanner(song);
		while (true) {
			if (sc.hasNext() == false) {
				break;
			}
			System.out.println(sc.next());
		}
		sc.close();
	}
}

 

 

- .nextLine() \n 전까지의 내용을 읽는 명령(\n은 버린다)

package api.util.scanner;

import java.util.Scanner;

public class Test04 {
	public static void main(String[] args) {
		String song = "떳다떳다 비행기 날아라 날아라\n떳다떳다 비행기 우리비행기";
//		System.out.println(song);

		Scanner sc = new Scanner(song);

		while (sc.hasNextLine()) {
			System.out.println(sc.nextLine());
		}

		sc.close();
	}
}

 

 

 

Scanner 응용 사용법

Scanner 의 특수기능 : 구분자(delimiter) 설정
Scanner는 기본 구분자가 공백이기 때문
구분자를 정규표현식(Regex)로 설정가능
next()의 구분 기준이 재설정되며 nextLine()은 변하지 않는다

package api.util.scanner;

import java.util.Scanner;

public class Test05 {
	public static void main(String[] args) {
		
//		String colors = "빨강/주황/노랑/초록/파랑/남색/보라";
		String colors = "빨강+주황,노랑?초록/파랑=남색-보라";
		Scanner sc = new Scanner(colors);
//		sc.useDelimiter("/");//슬래스(/)를 구분자로 인지하고 읽어라!
		sc.useDelimiter("[+,?/=-]");//더하기 또는 콤마 또는 물음표 또는 슬래시 또는 등호 또는 대시
		
		while(sc.hasNext()) {
			System.out.println(sc.next());
		}
		
		sc.close();
	}
}

빨강
주황
노랑
초록
파랑
남색
보라

 

 

- 키보드 입력 시 주의사항
next() 종류와 nextLine() 을 섞어서 사용하면 문제가 발생한다
next()는 공백(띄어쓰기, 개행)을 인식하는 명령(공백을 읽을 때 제거함)
nextLine()은 개행문자만 인식하는 명령(개행문자를 읽고 나서 제거함)
만약 next() 계열 명령 이후에 nextLine()을 사용해야 할 경우 nextLine()을 초기화를 수행하여 개행문자를 제거

package api.util.scanner;

import java.util.Scanner;

public class Test06 {
	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);

		System.out.println("입력");
		String a = sc.next();
		sc.nextLine();// 남아있는 개행문자를 정리하기 위하여 읽는 명령을 추가로 삽입
		String b = sc.nextLine();

		sc.close();

		System.out.println("a = " + a);
		System.out.println("b = " + b);
	}
}

입력
안녕
안녕 하세요
a = 안녕
b = 안녕 하세요

 

 

- 파일 객체 생성, readme.md 생성후 읽어 보기

package api.util.scanner;

import java.io.File;
import java.util.Scanner;

public class Test07 {
	public static void main(String[] args) {
		
		File file = new File("readme.md");
		try {
			Scanner sc = new Scanner(file);

			while (sc.hasNextLine()) {
				System.out.println(sc.nextLine());
			}

			sc.close();
		} catch (Exception e) {
			System.out.println("파일이 없습니다");
		}
	}
}

readme.md 내용

안녕

안녕하세요

 

 

-  Scanner를 이용하여 홈페이지 소스 읽기

package api.util.scanner;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Scanner;

public class Test08 {
	public static void main(String[] args) throws IOException {
		
		URL url = new URL("https://www.rottentomatoes.com/");

		Scanner sc = new Scanner(url.openStream(), "UTF-8");

		while (sc.hasNextLine()) {
//			<span class="dynamic-text-list__item-title clamp clamp-1">Cinderella</span>
			String line = sc
			.findInLine("<span\\s*class=\"dynamic-text-list__item-title\\sclamp\\sclamp-1\">(.*?)<\\/span>");// 원하는부분
																														
			if (line != null) {// 패턴과 일치하는 데이터를 찾은 경우
//					System.out.println(line);
//					첫 번째 > 와 마지막 < 의 위치를 찾아서 잘라내기
				int begin = line.indexOf(">") + 1;
				int end = line.lastIndexOf("<");

				System.out.println(line.substring(begin, end).replace("&#39;", "'"));
			} else {// 패턴과 일치하는 데이터를 못찾은 경우
				sc.nextLine();// 나머지 부분을 읽고 다음 줄로 이동
			}

		}

		sc.close();
	}
}

 

 

 

Collection - 기본설명

Collection Framework(JCF)
자바 표준 API에서 지원하는 저장 시스템 및 알고르짐 체계
기존에 존재하는 유명한 저장시스템 구현 알고리즘을 체계적으로 클래스화 시켜 사용할 수 있도록 만들어진 체계

유명한 저장 방식이란?
•스택(Stack) 방식 - Stack 클래스
•큐(Queue) 방식 - Queue 클래스
•데크(Deque) 방식 - Deque 클래스
•리스트(List) 방식 - List 클래스
•힙(Heap) 방식
•트리(Tree) 방식 - TreeSet, TreeMap 클래스..
•그래프(Graph) 방식
•해시(Hash) 방식 - HashSet, HashMap 클래스...

배열이 있는데 왜 저런걸 배워야 하나?


배열은 장점과 단점이 뚜렷하다

•장점 : 빠르다. 인덱스 연산이 가능하다.
•단점 : 크기 변경이 불가능하다. 메소드 지원이 부족하다.

배열을 이용하면 '크기가 불확실한 데이터'에 대해서 처리가 어렵다.
따라서 Collection Framework는 '가변 데이터 처리'와 '다양한 메소드 지원'이 특징이다.
순서가 중요하지 않음 Set 순서가 중요함 List

 

 

- TreeSet과 ArrayList를 통해 Collection 체계에 대해서 이해해보자!

package api.collection;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class Test01 {
	public static void main(String[] args) {
		
		Set<String> a = new TreeSet<String>();//전화번호부
		List<String> b = new ArrayList<String>();//통화내역
		
		a.add("아이유");	b.add("아이유");
		a.add("태연"); 		b.add("태연");
		a.add("박보영"); 	b.add("박보영");
		a.add("김을동"); 	b.add("김을동");
		a.add("차은우"); 	b.add("차은우");
		a.add("한지민"); 	b.add("한지민");
		
		System.out.println(a.toString());
		System.out.println(b.toString());
		
		
	}
}

a = [김을동, 박보영, 아이유, 차은우, 태연, 한지민] - 이름 순
b = [아이유, 태연, 박보영, 김을동, 차은우, 한지민] - 입력 순

 

 

 

- 리스트(List) 기능 알아보기
저장 순서를 유지(기억)하는 저장소
위치에 기반한 데이터 관리를 수행

package api.collection;

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

public class Test02 {
	public static void main(String[] args) {

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

		// 추가 - add()
		list.add("아이유");// 마지막 추가(index = 0)
		list.add("김을동");// 마지막 추가(index = 1 -> 2)
		list.add("박보영");// 마지막 추가(index = 2 -> 3)
		list.add("차은우");// 마지막 추가(index = 3 -> 4)
		list.add("태연");// 마지막 추가(index = 4 -> 5)
		list.add(1, "한지민");// 중간삽입(index = 1)

		// 출력
		System.out.println(list);

		// 개수 확인 - size() . 배열처럼 공간 개수가 아니라 "실제 데이터" 개수
		System.out.println(list.size());

		// 검색 - contains()
		System.out.println(list.contains("태연"));// 태연이 저장소에 있는가?
		System.out.println(list.contains("유재석"));// 유재석이 저장소에 있는가?

		// 확인 - get(index)
		System.out.println(list.get(3));// 3번 위치에 있는 이름은 무엇입니까?

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

		// 삭제 - remove()
		list.remove("한지민");
		list.remove(0);

		System.out.println(list);
		System.out.println(list.size());

	}
}

[아이유, 한지민, 김을동, 박보영, 차은우, 태연]
6
true
false
박보영
----------------
아이유
한지민
김을동
박보영
차은우
태연
[김을동, 박보영, 차은우, 태연]
4

 

 

 

- 과제

나라이름 대기 게임
사용자에게 나라이름을 지속적으로 입력받아서 저장하도록 구현
한 번이라도 입력한 적이 있는 나라를 다시 입력한 경우에는 게임 오버처리
게임 오버시 여태까지 입력한 나라 개수와 나라 목록을 출력하시면 됩니다.

package api.collection;

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

public class Test03 {
	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);
		List<String> country = new ArrayList<String>();

		while (true) {
			System.out.print("나라 이름을 입력하세요 : ");
			String name = sc.next();

			if (country.contains(name)) {
				System.out.println("중복입니다");
				break;
			}

			country.add(name);

		}

		sc.close();

		System.out.println("입력한 나라 개수 = " + country.size() + "개");
		System.out.println(country);

	}
}

- 정답

나라 이름을 입력하세요 : 한국
나라 이름을 입력하세요 : 미국
나라 이름을 입력하세요 : 한국
중복입니다
입력한 나라 개수 = 2개
[한국, 미국]