데브코스 백엔드 3기 4일차
Collection
추상체, 여러데이터의 묶음(덩어리)
- Collection의 구상체 : List -> List의 구상체 ArrayList, LinkedList, Vector, Stack
- Collection을 다루는 방법
- Iterator
- Stream
MyCollection.java 에서 foreach(), map(), filter() 구현해보기
public class MyCollection<T> {
private List<T> list;
public MyCollection(List<T> list) {
this.list = list;
}
- forEach()
- Consumer의 accept() : 인자는 존재, 반환값은 존재안함
public void foreach(Consumer<T> consumer) {
for (int i = 0; i < list.size(); i++) {
T data = list.get(i);
consumer.accept(data);
}
}
- map() : 데이터를 변경한다 = 이쪽 데이터에서 저쪽 테이터로 매핑한다
<U>
: 이 메서드 안에서만 유효한 제너릭 타입이라고 명시- list들을 function을 통해 U타입으로 바꾼다음에 U타입들만 모아진 MyCollection return
public <U> MyCollection<U> map(Function<T, U> function) {
List<U> newList = new ArrayList<>();
foreach(d -> newList.add(function.apply(d)));
return new MyCollection<>(newList);
}
- map() 사용
public class Main {
public static void main(String[] args) {
MyCollection<String> c1 = new MyCollection<>(Arrays.asList("A", "BC", "DEF"));
MyCollection<Integer> c2 = c1.map(String::length);
c2.foreach(System.out::println);
}
}
or
new MyCollection<>(Arrays.asList("A", "BC", "DEF"))
.map(String::length)
.filter(i -> i % 2 == 0)
.foreach(System.out::println);
.map()
하고나면 String type 받아서 그 String의 length를 Integer로.filter()
로 그 Integer 받아서 짝수면foreach()
로 출력
- filter()
- Predicate의 test() : 인자를 받고 boolean return
public MyCollection<T> filter(Predicate<T> predicate) {
List<T> newList = new ArrayList<>();
foreach(d -> {
if(predicate.test(d)) newList.add(d);
});
return new MyCollection<>(newList);
}
Iterator
데이터를 하나씩 떨어트려놓음
= Iterator라는 방식으로 여러 데이터의 묶음을 풀어서 하나씩 처리할 수 있는 수단 제공
- next() 통해서 다음데이터 조회가능 (but, 이전 데이터 조회 불가)
- 끝났는데 계속 next() -> exception
=> 데이터 있는지 확인필요 :if(iter.hasNext()) iter.next()
- 끝났는데 계속 next() -> exception
public interface MyIterator<T> {
boolean hasNext();
T next();
}
public class Main {
public static void main(String[] args) {
MyIterator<String> iter2 =
new MyCollection<String>(Arrays.asList("A", "BC", "DEF", "GHIJ"))
.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
}
}
- Iterator로는 전체 묶음 중에 위치 알 수 없음
- next()로 주어지는 현재데이터만 가지고 활용함
- Collection에서 쓰는 고차함수(forEach, map, filter)를 써서 데이터를 처리할 수는 없을까?
=> Stream
참고) 고차함수
함수형인터페이스를 사용해서 함수를 인자로 받는 함수
Stream
끊어지지 않는 연속되는 데이터들의 흐름
Stream도 데이터의 연속상에서 제공되는 데이터 하나만 취급
그러나 한건씩 처리하면서 고차함수 사용 가능
- 이미 우리가 쓰던 Stream
InputStream in = System.in;
OutputStream out = System.out;
- 자바 8부터 제공하는
Collections.stream()
은 조금 다름- Collection안의 데이터를 연속된 흐름으로 취급가능 + 고차함수 사용 가능 + 간결하게 표현가능
Stream() + 고차함수 사용
public class Main {
public static void main(String[] args) {
Arrays.asList("A", "BC", "DEF", "GHIJ")
.stream()
.map(String::length)
.filter(i -> i % 2 == 1)
.forEach(System.out::println);
}
}
- List의 stream()
Stream<Integer> stream = Arrays.asList(1,2,3).stream();
- Arrays의 stream()
- primitive type은 IntStream type으로 반환
boxed()
이용해서 wrappercollect(Collectors.toList())
이용해서 List로 반환toArray()
- Object[] return (primitive type array로 받을 때는 그냥 받아도 됨)
toArray(Integer[]::new);
: Integer[] return
IntStream intStream = Arrays.stream(new int[]{1,2,3});
Stream<Integer> stream2 = Arrays.stream(new int[]{1,2,3}).boxed();
List<Integer> list = Arrays.stream(new int[]{1,2,3}).boxed().collect(Collectors.toList());
Arrays.stream(new int[]{1,2,3}).boxed().toArray(); //Object[]
Arrays.stream(new int[]{1,2,3}).boxed().toArray(Integer[]::new); //Integer[]
- Stream 만드는 방법
.generate()
.iterate()
: 초기값 필요 -> 다음에 어떤 결과값 만들어 낼건지
Stream.generate(() -> 1)
.limit(10)
.forEach(System.out::println);
Stream.iterate(0, (i) -> i + 1)
.forEach(System.out::println);
Optional
- NPE(Null Pointer Exception)
- 자바에서는 거의 모든것이 레퍼런스 = 거의 모든것이 null이 될 수 있음
=> 항상 null 확인할 필요 있음 => 이제부터 null 쓰지마! 서로 약속! = 계약하고 프로그래밍한다
- 자바에서는 거의 모든것이 레퍼런스 = 거의 모든것이 null이 될 수 있음
null 안쓰는 법
- Empty 객체 사용
- Optional : null이 될 수 있는 값들을 운반할 수 있는 캐리어
1) Optional: User라는 객체를 래핑해서 운반해주는 운반체 운반체 안에 들어갈 수 있는 내용은 유저고 실제고 값이 있을수도 없을수도 있음 만약 실제 User가 없으면 null return이 아닌 null이 담긴 Optional 객체를 반환
Optional 사용
- null인 데이터 표시 :
Optional.empty()
Optional<User> optionalUser = Optional.empty();
- 데이터 넣어주기 :
Optional.of({DATA})
optionalUser = Optional.of(new User(1, "taehee"))
- 데이터 있는지
optionalUser.isPresent();
optionalUser.ifPresent(user -> {
//do 1
});
=> Optional type만으로 null일수도 있다는 걸 알 수 있음
[세션] 진유림님 Github 강의
- 협업 = Git(분산 버전관리) + Github(클라우드 저장소)
- Git : 원하는 시점마다 깃발꽂고(= 버전 만들고) 그 사이를 자유롭게 돌아다님
- branch : 하나의 원본저장소에서 분기 나눔
- 다수의 사용자가 다수의 브랜치 -> 관리힘듬
- 대부분의 회사가 사용하는 방식(토스도 이 방식 사용!)
- fork : 여러 원격저장소 만들어 분기나눔
- 원본저장소 이력을 보려면 따로 주소 추가해주어야 함
PR(Pull Request) = Merge Request
- feat/기능이름
- fix/버그이름
- hotfix/급한버그
=> 직접 커밋은 여기서만..!
이후부터는 merge만
-> dev(or main) -> release(or latest) -> 실서버에 배포
낯선 기능들
- amend : 커밋메세지만 수정
- stash : 변경사항 킵해두고 커밋은 아직 안하고 싶을 때
= 서랍에 넣어두기 + 메세지남기기 + 브랜치 왔다갔다- 브랜치 이동시에는 클린한 상태로(commit or stash해서)
- tracked 인 것만 들어감
- apply stash 후 stash 목록에서 지우기
- reset : 옛날 커밋으로 돌리기
- soft
- mixed : 과거로 돌아감 + 기억은 남김(working directory에 uncommited changes에)
- hard : 과거로 돌아감 + 아무것도 안남음
- revert : 이 커밋의 변경사항을 되돌리고 싶어! = 되돌리는 커밋을 만드는 것
- cherry-pick : 커밋 하나만 떼어서 지금 브랜치에 붙이는
- bug fix시 많이 사용
Stream 사용예제
1. 주사위를 100번 던져서 6이 나오는 횟수
- limit(숫자) : 숫자만큼 데이터를 가져와 새로운 스트림 생성해 반환
Random r = new Random();
long count = Stream.generate(() -> r.nextInt(6) + 1)
.limit(100)
.filter(n -> n == 6)
.count();
System.out.println(count);
2. 1-9 사이 값 중에서 겹치지 않게 3개를 출력
- distinct() : 중복제거
Random r2 = new Random();
int[] arr = Stream.generate(() -> r.nextInt(9) + 1)
.distinct()
.limit(3)
.mapToInt(i -> i)
.toArray(); //primitive type 인 경우에는 그냥 나옴 toArray(Integer[]::new); 안해줘도됨
System.out.println(Arrays.toString(arr));
3. 0-200 사이 값 중에서 랜덤값 5개를 뽑아 큰 순서대로 출력
- sorted() : 작은순서대로
- sorted(Comparator.reverseOrder()) : 큰순서대로
Random r3 = new Random();
int[] arr2 = Stream.generate(() -> r.nextInt(200))
.limit(5)
.sorted(Comparator.reverseOrder())
.mapToInt(i -> i)
.toArray();
System.out.println(Arrays.toString(arr));
일기(회고)
- 20일 TIL을 12시가 넘은 21일 새벽 2시에 쓰는중 ㅎㅎ
3시간 세션듣고(핑계대기) 오늘 많이 나태했고 와중에 컬렉션 내용은 너무 어렵고
그래도 깃헙 새로운 기능을 파악해서 뿌듯했다 나도 토스 가고싶다..!
- Iterator, Stream 너무너무 낯설어서 난 여태까지 무슨 자바공부를 했다는걸까 싶었던 어제오늘이었다
곰튀김님의 설명은 물흐르듯이 흘러가서 너무 신기하다
듣다보면 이래서 이렇게 되는구나! 한다 내공!
많이 써봐야 익숙해진다는 말 알아도 또 마음에 새기기
- 계산기 과제
fork한 repo에는 push해도 잔디가 안심기길래 다른방법을 이것저것 해보려다가 결국 원래 repo를 날렸다 ㅎㅎ
오늘 이거때문에도 시간을 많이 날림 Git 어렵워,,
내일부턴 설계 강의 듣고 설계 시작해봐야지
- 오늘의 귀여움
- 바텐더 나! 한잔에 삼만원