본문 바로가기
교육/Java&Spring

kosta 클라우드 네이티브 애플리케이션 개발 과정 day 15

by Renechoi 2023. 1. 9.

kosta 클라우드 네이티브 애플리케이션 개발 과정 day 15


지난주 과제였던 야구 게임 과제를 풀이해보자 ! 

 

package kosta.mission2.mission2_12.baseball;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Baseball baseball = new Baseball();

        int[] inputs = new int[3];
        int strike = 0;
        int ball = 0;
        int count = 0;


        do {
            System.out.println("도전 입력");
            for (int i = 0; i < 3; i++) {
                inputs[i] = scanner.nextInt();
            }
            count++;

            strike = baseball.countStrike(inputs);
            ball = baseball.countBall(inputs);

        } while (strike != 3);

        System.out.println("성공!");
    }
}
package kosta.mission2.mission2_12.baseball;

public class Baseball {
    int[] computers;

    public Baseball() {
        computers = new int[3];
        computers[0] = getRandom();

        do {
            computers[1] = getRandom();
        } while (computers[0] == computers[1]);

        do {
            computers[2] = getRandom();
        } while (computers[0] == computers[2] || computers[1] == computers[2]);

    }

    public int countStrike(int[] inputs) {
        int strike = 0;

        for (int i = 0; i < 3; i++) {
            if (computers[i] == inputs[i]){
                strike++;
            }
        }
        return strike;
    }

    public int countBall(int[] inputs) {
        int ball = 0;
        for (int i = 0; i < 3; i++) {
            if (computers[i] == inputs[(i + 1) % 3]) {
                ball++;
            } else if (computers[i] == inputs[((i + 2) % 3)]) {
             ball++;
            }
        }
        return ball;
    }

    private static int getRandom() {
        return (int) (Math.random() * 9) + 1;
    }
}

 

inner class, nested class 

 

 

네스티드 클래스 

 

성적표 클래스가 있고 과목별 성적을 필드로 갖는다고 해보자. 

 

class ExamResult { 
	String name;
    ItemResult result[];
    
    ...

 

class ItemResult {
	String subject
    ...
    }

 

 

이때 ItemResult 과목별 성적 클래스가 오로지 ExamResult만 위해서 존재한다면, ExamResult 안의 클래스로 표현할 수 있다. 

 

class ExamResult {
	String name;
    ItemResult result[];
    
    class ItemResult {
    	String subject;
        int score;
    }
}

이와 같이 내부 클래스 형식으로 표현할 수 있다. 

(일종의 필드 형식) 

 

class Car {
  int count;
  
  class Item { => field
  }
}

 

e.g.

Map.Entry entry 

=> 내부 클래스 형태의 데이터 타입 (인터페이스 안의 인터페이스 타입) 

 

 

 

Cart.Item item = cart.new Item("꽃다발", 1000);

 

 

 

익명 내부 클래스 

 

 

추상 클래스를 extends 해본다고 해보자. 

새로운 클래스와 + overriding + 객체 생성 + 호출의 작업이 필요하다. 

class SatelliteSender extends MessageSender {
	@Override
    void send(String message) {
    	System.out.println("발신 : 마이다스");
        System.out.println("발신 : 마이다스");
        System.out.println("발신 : 마이다스");
        System.out.println("발신 : 마이다스");
    }
}

SatelliteSender obj = new SatelliteSender();

 

하지만 이 메서드가 이 경우에만 사용되고 다른 데에서는 사용될 일이 없다면 어떨까? 

갑자기 급해서 이번 딱 한번만 쓴다면 ? 

 

익명 클래스를 통해 번거로움을 줄일 수 있다 ! 

 

MessageSender obj = new MessageSender(){
	void send(String message) { 
    	System.out.println("발신: 마이다스");
    }
}

 

List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
	public boolean test(Apple a) {
    	return RED.equals(a.getColor());
    }
});

- 모던 자바 인 액션 80p

 

 

interface나 abstract를 클래스를 소환할 때 IDE의 자동완성 기능을 이용할 수 있다. 

 

 

 

 

 

Role drive = new Role() {
    @Override
    public void doSomething() {
        System.out.println("drive !");
    }
};

Person person = new Person("홍", drive);

 

 

 

완전 1회용 익명 클래스는 다음과 같이 만들 수도 있다. 

 

Person person2 = new Person("김", new Role() {
    @Override
    public void doSomething() {
        System.out.println("coding !!!");
    }
});

 

 

* functional interface 참고자료 

 

자바에 미리 규정된 Functional interface 종류들 

 

  • Supplier<T> represents a supplier, which returns a value, type T.
  • Consumer<T> represents an operation that takes one parameter, type T, and consumes T. It returns void.
  • Function<T, R> represents a function that takes one parameter, type T, and returns a value, type R.
  • Predicate<T> represents a boolean-valued function that takes one parameter, type T, and returns a boolean.
  • BiFunction<T, U, R> represents a function that takes two parameters, type T and type U, and returns a value, type R.

(자료 출처 : https://medium.com/swlh/super-basic-java-anonymous-class-functional-interface-and-lambda-expression-fba411a787)

 

 


람다식 그리고 함수형 프로그래밍 ! 

 

함수형 프로그래밍이란 자바에서 시작된 것은 아니고 동적 프로그래밍을 실현하고자 하는 패러다임이다. 

자바에서는 8 이후 도입했다. 

 

현재 프로그래밍의 컨센서스 ! 

 

package kosta.basic.day015.lamdaEx;

public class LambdaMain {
    public static void main(String[] args) {
        // 1단계 myType => 익명 내부 클래스로 구현해보자
        // 2단계 lambda 
        // 3단계 한 줄 lambda

        MyType myType = new MyType() {
            @Override
            public void hello() {
                System.out.println("this is anonymous class!");
            }
        };


        MyType myType2 = () -> {
            System.out.println("this is lambda expression!");
        };

        myType.hello();
        myType2.hello();

        MyType myType3 = () -> System.out.println("this is lambda expression2!");

    }
}

 

 


 

java API 

 

Object 

 

자바의 모든 클래스는 Object를 상속하고 있다. 

 

 

Object를 상속하고 있기 때문에 equals를 쓸 수 있다. 

 

이때 runnable을 lamda 식으로 사용하면 3항 연산자에 동적 프로그래밍을 구현할 수 있다 ! 

 

Person person1 = new Person("kim", 20);
Person person2 = new Person("kim", 20);

Runnable identification = person1.equals(person2) ?
        () -> System.out.println("equals true!") :
        ()->System.out.println("equals not true!");

identification.run();

 

 

 

만약 두 person 객체가 같은 것으로 판단하려면 equals를 재정의해줄 수 있다 ! 

 

이름이 같은 경우 맞다고 판단하도록 equals를 재정의해주기 

 

@Override
public boolean equals(Object obj) {
    Person2 person2 = (Person2) obj;
    return name.equals(person2.getName()) && age == person2.getAge();
}

 

 

 

toString method를 overriding 한다면 이름만으로도 정보를 얻을 수 있다. 

 

@Override
public String toString() {
    return "Person2{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
}

 

 

Person person1 = new Person("l", 20);
System.out.println(person1);

Person2 person2 = new Person2("k", 20);
System.out.println(person2);

 

 

 

equals와 hashcode 재정의하기 

 

package kosta.basic.day015.api.object;

import java.util.Objects;

public class Person2 {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public boolean equals(Object person) {
        if (person == this) {
            return true;
        }

        Person2 person2 = (Person2) person;
        return name.equals(person2.getName()) && age == person2.getAge();
    }

    @Override
    public int hashCode() {
        // hashCode 재정의
//        return Objects.hash(0);
        return name.hashCode();
    }

    @Override
    public String toString() {
        return "Person2{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 

Equals를 재정의 했을 경우 

 

hashCode를 항상 재정의 해야 하는 이유 

 

Eqauls를 재정의한 클래스 모두에서 hashCode도 재정의해야 한다. 그렇지 않으면 hashCode 일반 규약을 어기게 되어 해당 클래스의 인스턴스를 HashMap이나 HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것이다. 다음은 Object 명세에서 발췌한 규약이다. 

 

- equals 비교에 사용되는 정보가 변경되지 않았다면, 애플리케이션이 실행되는 동안 그 객체의 hashCode 메서드는 몇 번을 호출해도 일관되게 항상 같은 값을 리턴해야 한다. 

 

- 이펙티브 자바 67p 

 

 


String 클래스 ! 

 

 

string 객체의 identification 

 

String string = "ABC";
String string2 = "ABC";
String string3 = new String("ABC");


Runnable identification = string.equals(string2) ?
        () -> System.out.println("equals true!") :
        () -> System.out.println("equals false!");

identification.run();

Runnable identification2 = string2.equals(string3) ?
        () -> System.out.println("equals true!") :
        () -> System.out.println("equals false!");

identification2.run();

Runnable identification3 = string == string3 ?
        () -> System.out.println("equals true!") :
        () -> System.out.println("equals false!");

identification3.run();

 

 

string 객체의 불변성 

=> 자기 자신의 값을 변경하지 않는다 

 

String string = "ABC";

string.concat("DEF");

System.out.println(string);                      // ABC
System.out.println(string.concat("DEF"));    // ABCDEF

 

 

 

java String의 독특한 자료 저장 방식 

 

스트링 풀을 이용 

 

 

https://www.digitalocean.com/community/tutorials/what-is-java-string-pool

 

 

 


 

 

 

 

String Concatenation example 

 

String string = "ABC";

string.concat("DEF");

System.out.println(string);                      // ABC
System.out.println(string.concat("DEF"));    // ABCDEF

// 동적쿼리문
String query = "select * from board";
int num = 10;
String query2 = "select * from board";
// "+" 연산자를 이용한 변경
if (num == 10) {
    query += "where num = 10";
    query2 = query2.concat("where num = 10");
}
System.out.println(query);
System.out.println(query2);

StringBuffer stringBuffer = new StringBuffer("select * from board");
stringBuffer.append("where num = 10");

System.out.println(stringBuffer);

 


getBytes => byte[] 배열로 변환해서 리턴한다.

toCharArray => char[] 배열로 변환하여 리턴한다.

 

byte[] bytesArray = QUERY.getBytes();
char[] charsArray = QUERY.toCharArray();

System.out.println(Arrays.toString(bytesArray));
System.out.println(Arrays.toString(charsArray));

 


 

 

스트링 클래스를 이용하여 palindrome 판별하기 ! 

 

 private static boolean isPalindrome1(String str) {
        // using StringBuilder
        if (str == null)
            return false;
        StringBuilder stringBuilder = new StringBuilder(str);
        return stringBuilder.reverse().toString().equals(str);
    }

 

 

알고리즘 구현하기 

 

    private static boolean isPalindrome2(String str){
        if (str == null)
            return false;
        
        int length = str.length();

        for (int i = 0; i < length / 2; i++) {
            if (str.charAt(i) != str.charAt(length - i - 1))
                return false;
        }
        return true;
    }

문자 찾기 퀴즈를 풀어보자 ! 

 

package kosta.basic.day015.api.string;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class StringQuiz1 {
    public static void main(String[] args) throws IOException {

        // TODO : 한 개의 문자열을 입력 받고,
        // 특정 문자를 입력 받아 해당 특정문자가 입력 받은 문자열에 몇 개 존재하는지 알아내보자

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

        String string1 = convertToSafeString(bufferedReader.readLine());
        String string2 = convertToSafeString(bufferedReader.readLine());

        // solution 1
        System.out.println(findCounts(string1, string2));

        // solution 2
        System.out.println(findCounts2(string1, string2));

        // solution 3
        System.out.println(findCounts3(string1, string2));

        // solution 4 => recursion
        System.out.println(findCounts4(string1, string2, 0));

    }

    private static int findCounts(String string1, String string2) {
        if (!string1.contains(string2)) {
            return 0;
        }

        return string1.length() - string1.replaceAll(string2, "").length();
    }

    private static int findCounts2(String string1, String string2) {
        return (int) string1.chars().filter(v -> v == string2.charAt(0)).count();
    }

    private static int findCounts3(String string1, String string2) {
        char[] alphabets = string1.toCharArray();

        int sum =0;
        for (Character alphabet : alphabets){
            sum = alphabet.equals(string2.charAt(0)) ? sum + 1 : sum;
        }
        return sum;
    }

    private static int findCounts4(String string1, String string2, int index) {
        if (index >= string1.length()) {
            return 0;
        }

        int count = string1.charAt(index) == string2.charAt(0) ? 1 : 0;
        return count + findCounts4(string1, string2, index + 1);
    }

    private static String convertToSafeString(String string) {
        return string.toLowerCase().trim();
    }
}

 

 

 


 

 

calender example 

 

private static void calenderUsageEx2() {
    Calendar calendar = Calendar.getInstance();

    String year = calendar.get(Calendar.YEAR) + "년";
    String month = calendar.get(Calendar.MONTH) +1 + "월";
    String date = calendar.get(Calendar.DATE) + "일";
    String hour = calendar.get(Calendar.HOUR) + "시";
    String minute = calendar.get(Calendar.MINUTE) + "분";

    System.out.printf("%s %s %s %s %s", year, month, date, hour, minute);
}

private static void calenderUsageEx1() {
    GregorianCalendar mereCalender = new GregorianCalendar();
    GregorianCalendar koreaCalender = new GregorianCalendar(Locale.KOREA);


    System.out.println(mereCalender);
    System.out.println(koreaCalender);


    Calendar calendar = Calendar.getInstance();
    System.out.println(calendar);
}

 

 


draw calender challenge 

 

package kosta.basic.day015.api.calender;

import java.util.Calendar;

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

        // 2023년 2월 달력 만들기
        // <2023년 2월>
        // 일 월 화 수 목 금 토
        //        1 2  3 4
        // 5 6 7 8  9  10 11

        int counts = getMonthCounts(2023, 2, 1);
        int dayBegins = getDayBegins(2023, 2, 1);

        char[] week = {'일', '월', '화', '수', '목', '금', '토'};

        int weekCounts = 0;
        weekCounts = weekCounts + dayBegins;

        StringBuilder stringBuilder = new StringBuilder();

        drawDays(week, stringBuilder);
        drawDates(counts, dayBegins, weekCounts, stringBuilder);
        
        System.out.println(stringBuilder);
    }

    private static void drawDates(int counts, int dayBegins, int weekCounts, StringBuilder stringBuilder) {
        stringBuilder.append("\t".repeat(dayBegins -1));

        for (int i = 1; i <= counts; i++) {
            stringBuilder.append(i).append("\t");
            weekCounts++;

            if (weekCounts == 8) {
                weekCounts = 1;
                stringBuilder.append("\n");
            }
        }
    }

    private static void drawDays(char[] week, StringBuilder stringBuilder) {
        for (char day : week) {
            stringBuilder.append(day).append("\t");
        }
        stringBuilder.append("\n");
    }

    private static int getDayBegins(int year, int month, int date) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, date);
        return calendar.get(Calendar.DAY_OF_WEEK);
    }

    private static int getMonthCounts(int year, int month, int date) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, date);
        return calendar.getActualMaximum(Calendar.DATE);
    }

}
반응형