TIL(Today I Learned)

Day.25 알고리즘 강의 문자열 chapter -끝- 그리고 CS

지팡구 2022. 12. 1. 22:35
Daily 알고리즘

https://jipang9-greedy-pot.tistory.com/101

 

문자열(String)을 이용한 문제 풀이 (3문제)

본 내용은 인프런 자바(Java) 알고리즘 문제풀이 : 입문 - 코딩테스트 대비 강의 문제를 기반으로 포스팅 한 내용입니다. 문제 문자거리 문자열 압축 암호(replace(), parseInt(string, 2)) 문제 1. 문자거리

jipang9-greedy-pot.tistory.com

 

Daily 알고리즘 총평 : 

오늘 문자열 챕터의 마지막 3문제를 정복하며

 

어떻게 코드를 더욱 간결하게 짤 수있을까?

어떻게 로직에 접근할 수 있을가? 

이 부분에는 어떻게 무엇을 사용하는게 좋을까? 라는

여러가지 생각을 하면서 직접 펜과 종이를 이용해 문제를 해결하는 시간을 가졌다.

 

뭔가 내가 구현하고자 한 방식과 해설강의가 똑같을땐, "아 내가 생각한 방식이 맞구나"

내가 구현한 방식과 해설강의 코드가 다를땐,  "이렇게 간결하게도 가능하네" 라는 생각을 하게 된다.


Daily 자바

오늘 CS 강의에선 인터페이스(Interface), 스트림(Stream), 옵셔널(Optional)을 다루었다.

 

과거에 인터페이스에 대해 한번 따로 정리해 놓은 부분이 있어서 그 부분을 참고하고, 또 다른 블로그나 강의에서 다루고 있는 인터페이스 내용을 통해 인터페이스를 완전히 이해하려고 노력했다.

 

우선 인터페이스이다. 

자바에선 클래스의 다중상속 (extends)을 지원하지 않아서 인터페이스를 이용해 다중 상속을 지원하고 있다.

이 때 인터페이스를 구현한 경우 반드시 인터페이스에 정의된 메서드들의 몸통을 만들어야한다.

(인터페이스에서는 메소드의 몸통만 만들고 이 인터페이스를 사용하고자 하는 곳에서 오버라이딩을 통해 메서드의 기능들을 구현해줘야 한다.)

 

또 이 인터페이스의 모든 필드는 public static final 이어야 하는데, 명시를 해주지 않고 생략하더라도 괜찮다.

이런식으로 말이다. 또한 밑에 선언된 메서드는 전부 다 추상 메서드이다. (public 뒤 abstract가 생략된 것)

 

자바 7에서는 final이나 abstract를 생략하면 자동으로 붙는다.

자바 8부터는 디폴트(default) 메서드와 정적(static) 메서드도 선언이 가능하다.


왜 자바 8부터 이렇게 했을까??

 

우선 디폴트 메서드가 필요한 이유는 다음과 같다.

 

만약에 우리가 인터페이스 A를 구현했다고 생각을 해보자, 그 속에는 a1과 a2라는 메소드가 존재한다

그럼 타인의 입장에서 이 인터페이스를 사용한다고 하면 a1과 a2를 둘 다 상속받아서 사용해야 한다.

그러던 도중 A 인터페이스가 버전업을 통해 a3 메소드가 추가됐다고 해보자

그럼 이 A인터페이스를 사용하는 사람들 입장에선 a3 메소드도 추가를 해야 당연히 에러가 안 날것이다.

그래서 이 때, 이 a3을 default메서드로 만들어서 구현을 해놓으면 자동으로 a3를 사용할 수 있다. 


그래서 컴파일이나 실행 오류가 안 난다. 이러한 문제를 해결하기 위해 default 메서드 선언이 필요하다.(하위호환성, 유연성)

 

 

다음은 static 메서드이다.

 

우선 이 인터페이스에서 정의한 static 메서드를 사용하기 위해선 인터페이스명.메서드 형식으로 호출해야 한다.

 

이 static 메서드를 인터페이스에 선언하면 인터페이스를 이용해 간단한 기능을 가지는 유틸리티성 인터페이스를 만들 수 있다.

 

이때 이 static 메서드는 override 불가능하다. 


다음은 옵셔널(Optional)이다.

이 옵서널을 나는 예외처리 시 사용해본 경험이 있다. 그때 대충 인터넷에서 검색해서 옵셔널이 무엇이였는지, 왜 쓰는지 알고있었는데, 지금 이렇게 정리하려고 하니 까먹었다....

 

우선 이 옵셔널은 객체를 편하게 처리하기 위해 만들어진 클래스인데,  java.util 패키지에 속해있다.

 

앞서 나는 이 옵셔널을 예외처리 시 사용해본 경험이 있다고 했는데, 이 옵셔널은 NPE(Null Pointer Exception) 예외를 Optional이 제공하는 메소드로 편하게 처리가 가능하지만 ,잘못 사용하면 다른 Exception이 발생할 수 있다. 

 

그래서 잘못 사용하면 코드가 지저분해지고, 의미 없는 동작이나, Side-Effect가 유발될 수 있다. 

 

그래서 이 Optional은 메소드 반환 타입으로만 사용하는 것이 좋다. (추가적으로 Optional은 Wrapper class)

('T' 타입의 객체를 포장해주는 래퍼 클래스 -> 그래서 Optional 인스턴스는 모든 타입의 참조변수 저장 가능)

 

이 Optional 객체에 접근할 떄는, get( ) 메소드를 이용해서 객체에 저장된 값에 접근할 수 있고, 이 객체에 저장된 값이 null이면 NoSuchElementExcetion 예외가 발세생한다. 그래서 이 get( ) 메소드를 호출하기 전에 isPresent (  ) 메소드를 사용해서 Optional 객체에 저장된 값이 null인지 여부를 확인 후 호출 하는 것을 권장한다.

 

참고 : http://www.tcpschool.com/java/java_stream_optional

 


마지막으로 스트림(Stream)이다.

스트림(Stream) 연속된 정보를 처리하는 데 사용하는데, (그럼 이 연속된 정보에는 무엇이 있을까? 배열? 컬렉션? )

일반적으로 연속된 정보를 처리할 때, 반복문이나 iterator을 사용하면 코드에 대한 가독성이 떨어지고, 코드가 길어질 수 있다. 그래서 스트림이 존재하는 것이다. 

 

하나의 장점은 별도의 멀티스레드 구현 없이 병렬처리(multi-threading)가 가능해진 점이다.

 

스트림의 구조는 다음과 같다

list.stream().filter(x->x>10).count()

- .stream() -> 스트림 생성

 컬렉션의 목록을 스트림 객체로 변환하는데, 여기서 스트림 객체는 java.util.steam 패키지의 stream 인터페이스를 말하고.

 이 stream()메소드는 Collection 인터페이스에 선언되어 있다.

 

- .filter(x-> x>10) -> 중개 연산

생성된 스트림 객체를 사용해, 중개 연산 부분에서 처리하는데, 이 부분에서 결과를 리턴하는 것은 아니다.

(이 중개 연산은 반드시 있어야 하는 것은 아님.)

 

- .count() -> 종단 연산

중개 연산에서 작업된 내용을 바탕으로 여기에서 결과를 리턴해주는데, 그래서 이 부분을 종단 연산이라고 한다.

 

stream()을 통해 데이터를 순차적으로 처리하게 되는데, 예를들어 10개의 데이터가 있다고 가정하면 0~9번째 인덱스를 하나씩 처음부터 처리하게 된다. 

 

참고  : https://ksr930.tistory.com/237

 

이 스트림은 직접 사용해보면서 사용법을 익히는 쪽이 가장 빠를것같다.