Fact
- 오늘 아침에 프로그래머스에 있는 문제 2개를 풀었다. 하나는 x 만큼 간격이 있는 n 개의 숫자, 하나는 최소 공배수 최대 공약수. 둘 다 Java로 풀었다. x 만큼 간격 문제는 들어오는 int 인자를 인덱스만큼 곱하면서 배열에 넣어줬다. 여기서 문제가 int 값이 42억이 넘어서 에러가 떴다. 그래서 long type로 바꿔 줘서 계산을 했다. 계산할 때 결괏값만 long으로 바꾸는 게 아니라 곱하는 수도 long으로 바꿔 줘서 계산해야 한다. 최대공약수 최대 공배수 문제는 예전에 JavaScript로 푼 방법을 가지고 Java로 옮겨 적어 봤다.
- 오늘 코어 자바 7~8장을 봤다. 책에 있는 코드들을 읽어 봤다. 읽어 본 후에 코드를 intelliJ에 쳐보면서 인풋을 새로이 하고 결과들을 봤다. 그리고 본 것을 TIL에 쓰면서 한번 정리를 해봤다.
Feelings
- Java로 문제 푸는 게 너무 빡세다. type 변환 퉤
- 책에서 볼게 너무 많다. 으엉
Findings
LinkedHashMap에서 accessOrder이라는 parameter이 있다. 이것을 true로 설정을 할 시에 access할 때마다 map에서의 위치가 달라진다.
accessOrder : false일 경우
LinkedHashMap<String, Integer> map1 = new LinkedHashMap<String, Integer>(16, 0.75f, true);
map1.put("first", 2);
map1.put("second", 3);
map1.put("third", 4);
map1.put("fourth", 5);
map1.get("first"); //2
map1.get("third"); // 4
map1.forEach((key, value) -> { System.out.println("Key:" + key + ", Value:" + value); });
//Key:second, Value:3
//Key:fourth, Value:5
//Key:first, Value:2
//Key:third, Value:4
accessOrder : true일 경우
LinkedHashMap<String, Integer> map1 = new LinkedHashMap<String, Integer>(16, 0.75f, true);
map1.put("first", 2);
map1.put("second", 3);
map1.put("third", 4);
map1.put("fourth", 5);
map1.get("first"); //2
map1.get("third"); // 4
map1.forEach((key, value) -> { System.out.println("Key:" + key + ", Value:" + value); });
// Key:second, Value:3
// Key:fourth, Value:5
// Key:first, Value:2
// Key:third, Value:4
public static void initialize(Map<String, Integer> weekdays) {
weekdays.put("Monday", 1);
weekdays.put("Tuesday", 2);
weekdays.put("Wednesday", 3);
weekdays.put("Thursday", 4);
weekdays.put("Friday", 5);
weekdays.put("Saturday", 6);
weekdays.put("Sunday", 7);
}
public static void main(String[] args) {
Map<String, Integer> weekdays = new HashMap<>();
initialize(weekdays);
System.out.println(weekdays);
// {Monday=1, Thursday=4, Friday=5, Sunday=7, Wednesday=3, Tuesday=2, Saturday=6}
// 랜덤하게 나온다
weekdays = new TreeMap<>();
initialize(weekdays);
System.out.println(weekdays);
// {Friday=5, Monday=1, Saturday=6, Sunday=7, Thursday=4, Tuesday=2, Wednesday=3}
// Key 순서에 따라 나온다
weekdays = new LinkedHashMap<>();
initialize(weekdays);
System.out.println(weekdays);
//{Monday=1, Tuesday=2, Wednesday=3, Thursday=4, Friday=5, Saturday=6, Sunday=7}
// 넣은 순서대로 나온다.
}
프로퍼티 컬렉션 텍스트 형식을 가지는 맵과 비슷한 것. String 값만 저장할 수 있다.(put 까진 되지만 저장 store은 안된다)
Properties settings = new Properties(); //Property 생성
settings.put("width", "200");// 그 Property에 property 넣기. settings 출력하면 {width=200}으로 나옴
settings.put("title", "Hello, World!");// 출력하면 {width=200, title=Hello, World!}
Path path = Paths.get("demo.properties");//path 지정
try (OutputStream out = Files.newOutputStream(path)) {
settings.store(out, "Program Properties");// 위에 setting들을 path로 지정된 파일에 저장.
}
settings = new Properties(); // setting 초기화
try (InputStream in = Files.newInputStream(path)) {
settings.load(in);// 파일에 저장되어 있는 것들을 불러와서 settings 에 저장함.
}
System.out.println(settings); // settings 출력
BitSet는 boolean 요소 Array다 BitSet를 출력하면 true인 bit의 index가 Array처럼 출력된다. 모든 bit는 false로 초기 설정이 되어 있다.
BitSet bitset = new BitSet(8);
bitset.set(0); // 0을 true로 만들기 bitset 출력시 {0} 나옴
bitset.set(1); // 1을 true로 만들기 bitset 출력시 {0, 1} 나옴
bitset.set(2);
bitset.set(3);
bitset.set(4);
bitset.set(5);
System.out.println(bitset); // {0,1,2,3,4,5}
bitset.set(1, 3, false); // 출력하면 {0,3,4,5}
bitset.clear(4); // 출력하면 {0,3,5}
열거 타입을 사용하고 싶을 때 EnumSet를 쓴다. 정적 팩토리 메서드로 집합을 생성 후 사용하면 된다.
enum Weekday { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY };
Set<Weekday> always = EnumSet.allOf(Weekday.class);// 모두 넣기
Set<Weekday> never = EnumSet.noneOf(Weekday.class);// 아무것도 안 넣기
Set<Weekday> workday = EnumSet.range(Weekday.MONDAY, Weekday.FRIDAY);// 범위 지정해서 넣기
Set<Weekday> mwf = EnumSet.of(Weekday.MONDAY, Weekday.WEDNESDAY, Weekday.FRIDAY);// 특정한것만 넣기
System.out.println(always);//[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
System.out.println(never);//[]
System.out.println(workday);//[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY]
System.out.println(mwf);//[MONDAY, WEDNESDAY, FRIDAY]
EnumMap<Weekday, String> personInCharge = new EnumMap<>(Weekday.class);// 열거 타입의 인스턴스를 키로 사용하고 맵을 사용하고 싶을때 EnumMap을 쓴다.
personInCharge.put(Weekday.MONDAY, "Fred");
System.out.println(personInCharge);//{MONDAY=Fred}
- 자료구조 스택, 큐, 덱(double end queue).
- 스택(Stack)은 한쪽 끝에서 추가하고 삭제한다.
- 큐(Queue)는 한쪽 끝에서 추가하고 다른 쪽 끝에서 제거한다.
- 덱(Double End Queue 혹은 Deque)는 양쪽 끝에서 추가와 삭제가 가능하다.
Stack
ArrayDeque<String> stack = new ArrayDeque<>();
Queue<String> queue = new ArrayDeque<>();
stack.push("Peter"); queue.add("Peter");
stack.push("Paul"); queue.add("Paul");
stack.push("Mary"); queue.add("Mary");
while (!stack.isEmpty()){
System.out.println(stack.pop());// Mary Paul Peter
}
while (!queue.isEmpty()){
System.out.println(queue.remove()); // Peter Paul Mary
}
priorityQueue라는 게 또 있다. 이것은 queue에 추가할 때마다 priority를 줘서 추가하는 queue이다. 그러나 쓰기 위해서 Comparable class를 만들어서 써야 한다.
// Comparable class 선언
public class Job implements Comparable<Job> {
private int priority;
private String description;
public Job(int priority, String description) {
this.priority = priority;
this.description = description;
}
public int compareTo(Job other) {
return priority - other.priority;
}
public String getDescription() {
return description;
}
}
// 선언한 Comparable 사용
public static void main(String[] args) {
PriorityQueue<Job> jobs = new PriorityQueue<>();
jobs.add(new Job(4, "Collect garbage"));
jobs.add(new Job(9, "Match braces"));
jobs.add(new Job(1, "Fix memory leak"));
while (jobs.size() > 0) {
Job job = jobs.remove(); // 4,9,1 순서로 나왔지만 priority가 1인 "Fix memory leak" 가 먼저 나온다.
System.out.println(job.getDescription());
}
}
//
약한 해시 맵이라는 게 있다. 약한 해시 맵은 해시 맵 안에 있는 키들 중 키가 더 이상 사용되지 않는 것을 가비지 컬렉터랑 협동을 하여 그 키/값 쌍을 제거한다.
범위로 가져와야 할때 쓰는 subList, subSet,tailSet subList(fromIndex, amountFromIndex0) subSet(from, untillBefore) 은 정렬된것을 범위를 잡아서 뽑아준다. 정렬 기준은 ascii code이다.
List<String> sentence = List.of("A man, a plan, a cat, a ham, a yak, a yam, a hat, a canal, Panama!".split("[ ,]+"));
System.out.println(sentence);//[A, man, a, plan, a, cat, a, ham, a, yak, a, yam, a, hat, a, canal, Panama!]
List<String> nextFive = sentence.subList(5, 10);
System.out.println(nextFive); //[cat, a, ham, a, yak]
TreeSet<String> words = new TreeSet<>(sentence);
words.add("zebra");
System.out.println(words);
SortedSet<String> ysOnly = words.subSet("A", "z");
System.out.println(ysOnly);// [A, Panama!, a, canal, cat, ham, hat, man, plan, yak, yam,]
// 두번째 parameter 범위는 포함되지 않는다. zebra도 뽑고 싶으면 subSet("A", "}"); 로 하면된다. "z" 다음 ascii code 가 "}" 다.
SortedSet<String> nAndBeyond = words.tailSet("p");
System.out.println(nAndBeyond);// [plan, yak, yam, zebra]
}
- java 8 에서부 터 stream이라는 library를 쓸 수 있게 되었다.
- 이것은 일련의 요소들을 연쇄적으로 처리하기 위해서 있는 class의 모음이다.
- 스트림을 이용하면 필터링과 카운팅을 확인할 필요가 없다.
- 메서드 이름을 보고 그 메서드의 의도가 드러난다.
- stream 사용 시 병렬적으로 처리할 수 있는 parallelStream 기능이 있다.
-
stream을 다룰 때는 보통 작업 흐름은 이렇게 된다:
- 스트림 생성.
- 초기 스트림을 다른 스트림으로 변환하는 중간 연산 지정.
- 종료 연산으로 결과를 뽑는다.
- stream 다양한 메서드들
-
map, filter, substring
String[] song = { "row", "row", "row", "your", "boat", "gently", "down", "the", "stream" }; Stream<String> firstChars = Stream.of(song).filter(w -> w.length() > 0).map(s -> s.substring(0, 1)); // Stream.of는 stream으로 바꾸는것 // filter은 조건에 따라 제외 시키는것. // map는 각 요소에 따라 바꾸는것 // substring(a,b)은 string의 a번째 인덱스 부터 b번째의 요소까지만 뽑는다. show("firstChars", firstChars); // [r, r, r, y, b, g, d, t, s]
- takeWhile, dropWhile
takeWhile은 filter랑 while 두 개 조합한 거랑 비슷하다. 예를 들어보자
``` java
// takeWhile
List<Integer> numbers = List.of(1, 2, 3, 10, 15, 1,5).stream().takeWhile(i -> i<10 ).collect(toList()); // nubmers = 1,2,3 이다 takeWhile 안에 있는 조건을 만족 시키지 않을 시에 바로 멈춘다.
//dropWhile
List<Integer> numbers = List.of(1, 2, 3, 10, 15, 1,5).stream().dropWhile(i -> i<10 ).collect(toList()); // numbers = 10,15,1,5 이다. dropWhile은 takeWhile 반대로 나머지를 가져온다.
기타 스트림 변환방법
- distinct, sorted, reversed, peek
distinct는 set처럼 stream 요소들 중 중복되는 것을 제외한다.
sorted는 sort처럼 조건에 따라 sort를 해준다.
reversed는 말 그대로 reverse 해준다.
peek는 원본과 같은 요소를 담은 새로운 스트림을 돌려준다.
Stream<String> uniqueWords = Stream.of("merrily", "merrily", "merrily", "gently").distinct();
show("uniqueWords", uniqueWords);// uniqueWords: [merrily, gently]
Object[] powers = Stream.iterate(1.0, p -> p * 2).peek(e -> System.out.println("Fetching " + e)).limit(20).toArray();
// Fetching 1.0
// Fetching 2.0
// ...
// Fetching 524288.0
System.out.println(Arrays.toString(powers));// [1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 2048.0, 4096.0, 8192.0, 16384.0, 32768.0, 65536.0, 131072.0, 262144.0, 524288.0]
Future Action
- 자바 프로그래머스 문제를 푸니깐 많이 배우게 되었다. 다음에도 많이 풀어서 공부해보자.
- 책을 읽고 코드를 쳐보고 수정도 해보니깐 배우는 게 많았던 것 같다. 그냥 읽는 것보단 더 많이 배우는 것 같으니 다음에도 코드를 가지고 놀면서 공부하도록 하자.