1. Collection 2. Iterator 3. Stream 4. Optional |
Collection
- 여러 데이터의 묶음을 Collection이라고 한다.
- Collection은 추상체
- Collection의 구상체 : List, set
- List의 구상체 : LnkedList, ArrayList, Vector, Stack
- Set의 구상체 : HashSet
- Collection의 구상체 : List, set
Iterator
- 여러 데이터의 묶음을 풀어서 하나씩 처리할 수 있는 수단을 제공한다.
- next()를 통해서 다음 데이터를 조회할 수 있다.
- 앞 쪽 방향으로 방향을 바꿀 수 없다. --> 이전 데이터 조회 불가
Stream
- Java 8 이상에서 부터 사용 가능.
- 데이터의 연속을 나타냄
- Collections.stream() 을 제공, stream() 메서드는 List 인터페이스에서 제공해주는 메서드
- filter, map, forEach 같은 고차함수(함수를 인자로 받는 함수)가 제공됨
- 스트림을 사용하면 연속된 데이터에 대해서 풍부한 고차함수들을 사용하여 강력한 기능을 간결하게 표현 가능
InputStream in = System.in;
OutputStream out = System.out;
//키보드 입출력도 연속된 데이터의 흐름이다
- stream() 메서드를 수행하면서 위의 Collection, Iterator와 달라진 점은
- 이전 방식에서는 .map() .filter() .forEach 각 단계를 수행하면서 Collection 덩어리 전체를 연산하고 다음 단계로 데이터를 넘겼다면
- stream을 사용한 방식에서는 데이터 하나가 모든 단계를 거친 후 다음 데이터, 다음데이터 .. 이러한 방식이다.
IntStream s1= Arrays.stream(new int[]{1,2,3});
Stream<Integer> s = Arrays.asList(1,2,3).stream();
//int형은 primitive 변수이기 때문에 제네릭에 사용할 수 없으므로 Stream<Integer> 이러한 변수로 사용할 수 없음
//IntStream : int 배열 객체를 위한 타입
Stream<Integer> s2= Arrays.stream(new int[]{1,2,3}).mapToObj(i -> Integer.valueOf(i));
stream<Integer> s3 = Arrays.stream(new int[]{1,2,3}).boxed();
//이런식으로 primitive 변수의 배열을 boxing 하여 Stream<Integer> 배열로 바꿀 수 있다.
Arrays.stream(new int[]{1,2,3}).boxed().collect(Collectors.toList());
/*
--> toList할 때는 collect()라는 기능을 사용. 이렇게 하면 List<Integer> 타입으로 결과가 나오게 됨
1. boxed()로 변수의 타입을 int -> Integer, 즉 primitive -> wrapper 타입으로 boxing 시킴
2. collect함수에서 Collectors.toList()로 다시 변화시켰기 때문에 List형으로 바뀜
*/
Arrays.stream(new int[]{1,2,3}).boxed().toArray(Integer[]::new); //integer[] 타입
Arrays.stream(new int[]{1,2,3}).boxed().toArray(); //Object[] 타입
- Stream 생성 : 2가지 방법이 있음
- Stream.generate();
- Stream.iterate();
1. Stream.generate()
- stream은 new 해서 만들수 없다.
Stream.generate()는 input값으로 Supplier가 들어간다.(input값은 없고 결과값만 있는 거) - Stream.generate()의 매개변수로 입력한 데이터를 연속해서 출력한다.
- straem은 연속된 데이터가 소진될 때 까지 실행되는데 generate하면서 1을 계속 발생시킨 것
//무한 "1" 출력 . . .
Stream.generate(() -> 1).forEach(System.out::println);
//무한 랜덤값 출력
Random r = new Random();
Stream.generate(() -> r.nextInt()).forEach(System.out::println);
//랜덤값 10개 출력
Random r2 = new Random();
Stream.generate(() -> r2.nextInt()).limit(10).forEach(System.out::println);
2. Stream.iterate()
- Stream.iterate()는 매개변수 2개가 필요하다.
- Stream.iterate(0,(i) -> i + 2)
- seed : 0 //초기값
- function : UnaryOperator extends Function<T, T> //입출력값을 가지는 함수형 인터페이스인 Function을 상속
Stream.iterate(0,(i) -> i + 1).forEach(System.out::println); //1,2,3,4... 무한으로 숫자가 올라가면서 출력됨
Stream을 생성하는 두 메서드의 차이점
- generate() : 초기값이 없다. --> 함수로 Supplier가 사용됨
- iterate() : 초기값(seed)가 있다. --> 함수로 Function<T,R>이 사용됨
Collection ~ Stream 까지의 내용 정리
여러개의 데이터의 묶음을 Collection이라고 함.
데이터 묶음을 하나하나 처리하고 싶을 때 Iterator 방식을 사용한다.
하지만 iterator는 Collection처럼 고차함수를 사용할 수 없다.
이를 해결하는 방법으로 Stream을 사용한다.
stream() 메서드는 List 인터페이스에서 제공해주는 메서드이기 때문에
Collection의 구상체인 List는 Collection 처럼 고차함수를 사용할 수 있게 해준다.
Optional
- NPE : Null Pointer Exception - 가장 많이 발생하는 에러중의 하나
- 자바에서는 (거의) 모든것이 레퍼런스 ==> (거의) 모든것이 null이 될 수 있다.
- null을 사용하지 않고 프로그래밍 하는 방향으로 해야 함
null을 사용하지 않는 방법!
(1) EMPTY 객체를 사용하는 방법
User user = new User(22,"강희정");
//이러한 형식의 객체가 있을 때
User user = null; //이런식으로 값으로 null이 들어갈 수도 있지만 사용하지 않는 방향으로 해야됨--> NPE 발생하니까 안됨
User user = new User(0,"");
//이런식으로 프로그램이 이해하지 못하게 임의로 null처럼 지정하는 방식도 나중에 문제가 발생할 수 있다. 때문에 EMPTY 객체를 사용해야됨
// ... User 객체 선언부
public static final User EMPTY = new User(0, "");
//이런식으로 EMPTY를 상수로 선언할 경우에는 임의로 null을 지정할 필요 없이 깔끔하게 코딩 가능
// .getUser()이런 함수로 (user.getUser() == null) 이러한 비교식 대신 (user == User.Empty) 이렇게 깔끔하게 비교 가능하다.
//User 내부에서도 (this == EMPTY) 이렇게 활용 가능
(2) Optional을 사용한다.
- null이 될수도 있는, 안될수도 있는 값들에 대해서 mapping해주는 것
Optional<NewObject> optionalObject = Optional.empty(); //null일때
optionalObject = Optional.of(new NewObject(1, "2")); //값을 넣을 때
- Optional은 NewObject라는 데이터를 wrapping해서 운반해주는 운반체(값이 있을수도 있고 없을수도 있음). null이 될 수 있는 값들을 운반해주는 운반체
- 그렇기 때문에 이 변수를 사용하게 되었을때 NewObject가 null이라면 진짜로 null이 아니라 비어있는 Optional을 반환하게 된다.
더보기
Optional 메서드
null 데이터 : Optional.empty()
데이터 : Optional.of( {DATA} )
확인하는 방법은 : .isEmpty(), .isPresent()
사용할 때 : optionalUser.get()
- EMPTY 방법은 EMPTY의 존재를 아는 사람들만 사용하는데,(존재를 확실하게 모름)
- optional방식은 어떻게 취급해야하는지 명확하게 알 수 있음(타입으로 존재하기 때문에 메서드도 정해져있어 사용하기 수월함)
- @NonNull을 사용하는 방식도 있지만 표준자바에서 제공해주는 방식은 아님(제공이 되는경우 적극적으로 활용하는 방법도 괜찮음)
'TIL' 카테고리의 다른 글
[TIL] 210809 (0) | 2021.08.10 |
---|---|
[TIL] 210806 (0) | 2021.08.09 |
[TIL] 210804 (0) | 2021.08.05 |
[TIL] 210803 (0) | 2021.08.05 |
[TIL] 210802 (0) | 2021.08.04 |