[데브코스] Collection 이야기
Updated: Categories: TILW1D4 - 우리가 자주 쓰는 Collection에 대해 깊게 파보자!
Collection
- 여러 데이터구조의 묶음.
- 기본적으로 추상체이며, 구상체로 구현되어 있음
getter? 지양하자
- getter를 사용하게 되면 클래스 멤버 변수에게 바로 접근이 가능하게 된다.
- 따라서 host code 레벨에서 get으로 변수를 받아 처리하는 것이 아닌, 처리하고픈 기능을 클래스 내부에서 구현해놓는 것이 좋다.
Iterator
- 여러 데이터 묶음을 풀어서 하나씩 처리할 수 있는 수단을 제공하는 컬렉션
- 컬렉션 내부에서 index 상태를 관리한다
- forEach 까지는 제공 X
List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4));
Iterator iterator = list.iterator();
// hasNext : 다음 인덱스 존재여부 판단
// next : 현재 인덱스에 해당하는 값 리턴
while(iterator.hasNext()){
System.out.println(iterator.next());
}
Stream
- Java 8이상부터 컬렉션 스트림 사용가능, 데이터의 연속이라고 생각하면 된다.
- 고차함수들을 가진다. (람다함수?를 파라미터로 받는 메소드)
- 컬렉션들은 모두 스트림 변환 메소드를 가지고 있어, 객체 Type을 스트림으로 변환 가능 =>
.stream()
Method Chaining
을 통한 연속적인 데이터 처리가 가능하다
List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4));
// 스트림으로 변환
Stream<Integer> s = list.stream();
Stream 메소드 정리
- 예전에 학교에서 수강한 데이터분석에서 스트림 메소드를 정리했었는데, 이게 또 나올줄이야…. 😫
- 다시보니 나름 잘 정리한것 같아서 앞으로 참고하자 -> 🚀 Repo 링크
Stream 만들기
- 컬렉션을 스트림으로 변환하지 않고 바로 만드는 것도 가능하다.
- 두 가지 방법으로 생성 가능.
// generate(넣을 값) -> 무한루프임 (limit이 없기에)
Stream.generate(1)
// iterate(시작값, 'Function' F-I)
Stream.iterate(0, i -> i+1)
Type의 이해
- Type 종류는 크게 세가지가 있다.
Primitive Type
: int, char 등등..Reference Type
: 컬렉션 객체Wrapper Class
: Primitive 타입을 담기위한 그릇이다. 기본적으로 얘도 Reference Type.
- 스트림도 객체이므로 Primitive Type은 type 지정이 불가하다.
- Primitive Type을 스트림으로 만드는 경우엔 별도의 스트림 객체가 만들어진다
Stream에서의 타입 변환
- stream에서의 Primitive Type은
___Stream
이라는 Wrapper class로 표현한다.
- ___Stream -> Stream 타입 변환은 map 메소드를 사용해도 되지만
boxed
메소드로도 가능
IntStream s = Arrays.stream(new int[]{1,2,3});
// IntStream -> Stream<Integer> : primitive 타입을 wrapper 타입으로 박싱하여 반환한다.
s.boxed()
- Stream -> ___Stream 타입 변환은
mapToXXX
메소드로 가능
// int -> IntStream
IntStream a = Stream.generate(() -> 1)
.limit(5)
.mapToInt(i -> i);
- ??? -> 컬렉션 변경은
collect
메소드로 가능
IntStream s2 = Arrays.stream(new int[]{1,2,3});
// int 배열 -> List
s2.boxed().collect(Collectors.toList()).forEach(System.out::println);
Optional
- NPE(Null Pointer Exception) : 자바에서는 모든게 레퍼런스 -> 모든것이 null이 될 수 있다.
- 따라서 항상 null을 확인할 필요가 있어 매우 귀찮음..
- 이제 null을 쓰지 않기로 계약하자!! (하지만 초기화할땐 어떡하지?)
EMPTY 객체 사용하기
- 클래스를 생성할때 그 클래스에 초기값 객체를 미리 전역으로 생성해 해놓는다.
- Null인지를 확인하지 않고 초기값 객체인지를 본다
public class User {
// 초기화를 위한 객체를 미리 만들어 놓는다.
public static User EMPTY = new User(0, "");
...
// 객체 생성할때 초기값 객체를 가져옴
User user = User.EMPTY;
// Null 확인이 아닌, 객체를 확인
if(user == User.EMPTY){
...
}
- 하지만 정해진 규칙없이 임의로 만드는것이기 때문에 모두가 규칙을 알기 힘들다.
Optional 사용하기
- 모두가 알 수 있는 명확한 사용법
- Null 사용을 방지하면서 값이 실제로 들어있는지 확인하기 위한
Wrapper
클래스
Optional<User> optionalUser = Optional.empty();
optionalUser = Optional.of(new User(1, ""));
// 값이 없다면 true
optionalUser.isEmpty();
// 값이 있다면 true
optionalUser.isPresent();
// 값 유무에따라 조건 실행
optionalUser.ifPresentOrElse(
// 있다면 (Consumer)
user -> { },
// 없다면 (Runnable)
() -> { }
);