static 정적 변수의 속도에 대한 고찰
static 변수를 만들어서 참조하면 지역변수(파라미터)보다 시간이 많이 소요.
시간에 예민한 문제들은 int 변수 1개라도 파라미터로 선언해주자
<Input>
Scanner sc = new Scanner(System.in);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in))
sc.nextByte() // byte 형 입력 및 리턴
sc.nextShort() // short 형 입력 및 리턴
sc.nextInt() // int 형 입력 및 리턴
sc.nextLong() // long 형 입력 및 리턴
sc.nextFloat() // float 형 입력 및 리턴
sc.nextDouble() // double 형 입력 및 리턴
sc.nextBoolean() // boolean 형 입력 및 리턴
sc.next() // String 형 입력 및 리턴(공백을 기준으로 한 단어를 읽음)
sc.nextLine() // String 형 입력 및 리턴 (개행을 기준으로 한 줄을 읽음)
//a를 기준으로 split()한다는 의미임, 둘 중 아무거나 써도됨
br.readLine().split("a");
StringTokenizer st = new StringTokenizer(br.readLine(),"a");
st.hasMoreTokens() //사용할 수 있는 토큰이 더 있는지 확인 true/false로 반환
st.countTokens(); //뒤에 토큰이 몇 개 남아있는지 확인
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
for (int i=0;i<2;i++) {
st = new StringTokenizer(br.readLine()); //라인개행으로 split()
for (int j=0;j<4;j++)
data[i][j] = st.nextToken();
}
<Output>
StringBuilder sb = new StringBuilder();
sb.append("123").append(1).append(" ") ....
sb.setLength(sb.length()-2); //인자의 개수만큼 출력이 잘리게 된다
sb.insert(0,"aaa ");// index에 해당하는 위치에 결과값을 넣는다
System.out.println(sb.toString());
for std: value (In python : for c in data:)
for each는 존재하는 값까지 돌리는게 아니라 배열 크기 모두 돌리는 거라서 NullPointerException 조심
for (char c : data)
System.out.println(c)
<String>
String str = "abcde";
str.length() // str의 길이 반환
str.isEmpty() // str의 길이가 0이면 true, 아니면 false
str.charAt(2) // 인덱스로 문자 찾기, c 반환
str.indexOf("c") // 문자로 첫번째 인덱스 찾기, 2 반환
str.indexOf("cd") // 2
str.indexOf("z") // -1
str.lastIndexOf("c") // 문자의 마지막 인덱스 찾기, 2 반환
str.substring(2, 4) // 2~3 위치의 문자열 "cd" 반환
str.substring(3) // 3부터 끝까지의 문자열 "de" 반환
str = str.replace('b', 'k') // b를 k로 변경 (akcde)
str.equals("abcde") // str과 abcde를 비교해서 같으면 true, 다르면 false
str.contains("bc") // str에 bc가 포함되어 있으면 true, 아니면 false
str.contains('b')
str.contains("b")
str.split(" ") // 띄어쓰기로 구분된 문자열 str을 분리해서 String[] 배열 반환
str.split() // 띄어쓰기 없는 문자열 str을 한 문자씩 분리해서 String[] 배열 반환
str.trim() // str의 앞뒤 공백 제거, 문자열 사이 공백은 제거 X
str.toLowerCase() // 대문자를 모두 소문자로 변경
str.toUpperCase() // 소문자를 모두 대문자로 변경
char data[] = str.toCharArray(); //char 배열로 변경
str.compareTo("abcdd")
/*
str과 abcdd가 같으면 0
str이 abcdd보다 사전순으로 앞이면 -1
str이 abcdd보다 사전순으로 뒤면 1
str과 abcdd가 마지막 문자만 다르면 마지막 문자의 사전순 차이 반환 (여기선 1)
*/
Integer.parseInt("300") // 문자열을 숫자로 변환
Integer.toString(300) // 숫자를 문자열로 변환
String str = new StringBuilder(words).reverse().toString(); //문자열 뒤집기
** String안에서 특정 문자열 찾기
String data = "aabb";
String std = "ab";
//1. replace : "ab" to "" 해버리면 새로운 문자가 생기게 되므로 안됨
//2. for문 - indexOf : for문 완탐보다는 String.indexOf() 이용해서 찾자
<List>
List<String> list = new ArrayList<>();
list.add("서울") // list의 가장 뒤에 서울 삽입
list.add(1, "대전") // 1 위치에 대전 삽입
list.addAll(list2) // list의 뒤에 list2의 모든 값 삽입
list.get(0) // 0 위치의 값 반환 (서울)
list.set(0, "대구") // 0 위치의 값을 대구로 변경
list.indexOf("대구") // 대구의 첫번째 인덱스 반환
list.lastIndexOf("대구") // 대구의 마지막 인덱스 반환
list.remove(0) // 0 위치의 값 삭제
list.remove("대구") // 첫번째 대구 삭제
list.removeAll(list2) // list에서 list2에 들어있는 모든 값을 삭제
list.retainAll(list2) // list에서 list2에 들어있는 값을 제외한 모든 값을 삭제
list.clear() // 전체 값 삭제
list.isEmpty() // 길이가 0이면 true, 아니면 false
list.size() // 길이
list.contains("서울") // 서울이 list에 있으면 true, 없으면 false
list.containsAll(list2) // list에 list2의 모든 값이 포함되어 있으면 true
list.removeIf(k -> k % 2 != 0) // 람다식으로 홀수를 list에서 모두 제거
list.toString() //출력
List<List<Integer>> board = new ArrayList<>(); //2차원에 대한 틀을 먼저 만든다음에
for (int i = 0; i < n + 1; i++)
board.add(new ArrayList<>()); //이런식으로 공간을 만들어줘야함
byte[] byte_array = { 10, 20, 30, 40, 50 };
List<Byte> byte_list = Arrays.asList(byte_array);
//깊은 복사 x (얕은 복사라서 값이 이상하게 나올 수 있음)
List<Byte> slice = byte_list.subList(1,3); // {20, 30}, list Slice
//무조껀 new로 해서 새로 만들어줘야함
List<Integer> front = new ArrayList<>(list.subList(0, idx));
<Collection>
int[] arr = { 1123, 1412, 23, 44, 512132 };
List<Integer> list = new ArrayList<>(Arrays.asList(arr));
Collections.max(list) // list의 원소 중 가장 큰 값 반환
Collections.min(list) // list의 원소 중 가장 작은 값 반환
Collections.sort(list) // list 오름차순 정렬
Collections.sort(list, Collections.reverseOrder()) // list 내림차순 정렬
Collections.reverse(list) // list 역순 정렬 { 512132, 44, 23, 1412, 1123 }
Collections.frequency(list, 23) // list 내의 23의 갯수 반환
Collections.binarySearch(list, 44)
// 최초로 검색된 44의 인덱스 1 반환
// 없으면 44보다 큰 최초의 위치 2를 찾아서 -1을 곱하고 1을 빼서 반환 (-3)
<Map>
Map<String,Integer> map=new HashMap<>();
map.put("str",1); // 값 넣기
map.get("str"); // 값 가져오기
map.containsKey("str"); //key값 존재 확인
map.size() // 사이즈
HashMap<Integer, String> map = new HashMap<>();
map.put(5, "abc");
map.put(3, "def");
map.put(10, "ghi");
TreeMap sortedMap = new TreeMap(map);
TreeMap reverseMap = new Treemap(Collections.reverseOrder());
System.out.println(sortedMap); //key에 대해 정렬 하고 싶을 때 TreeMap 사용
//첫 번째, Iterator를 통해 접근하기
Map<String, String> map = new HashMap<>();
Iterator<String> keys = map.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
map.get(key);
}
//두 번째, entrySet으로 접근하기
//Map은 하나의 원소로 Key-Value 묶음을 가지기 때문에 원소란 표현 대신 Entry라고 표현한다
Map<String, String> map = new HashMap<>();
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
}
//세 번째, 두 번째 방법이랑 비슷한데 entrySet이 아니라 keySet을 이용해 접근하기.
Map<String, String> map = new HashMap<>();
for (String key : map.keySet()) {
map.get(key);
}
<Queue>
list처럼 뒤에 추가하고 poll하면 앞에부터 pop시킴
Queue<Integer> queue=new LinkedList<>();
Queue<Integer> queue=new ArrayDeque<>(); //LinkedList보다 더 빠름
queue.add(1); //삽입
int que=queue.poll(); //꺼내기
queue.peek() //가장 최근에 추가한 데이터
<Stack>
Stack<Integer> s = new Stack<Integer>();
s.push(1); // 삽입
s.push(2);
while(!s.isEmpty()) { //비어있을때까지 돌리기
System.out.println(s.pop()); //스택이니까 가장 끝값 pop
}
s.peek() //가장 마지막으로 add한 값 (stack[-1])
<Set>
Set<String> temp = new HashSet();
for (int i = 0; i < n; i++) {
temp.add(br.readLine());
}
List<String> list = new ArrayList<>(temp); //리스트로 바꿔서
<Deque>
Deque<String> stack = new ArrayDeque<>();
stack.addFirst("Element1");
System.out.println(stack.removeFirst());
System.out.println(queue.removeLast());
<PriorityQueue>
PriorityQueue<Integer> pq= new PriorityQueue<Integer>(); //오름차순(minHeap)
PriorityQueue<String> pq= new PriorityQueue<String>();
System.out.println(pq.peek()); // minHeap
PriorityQeueu<Integer> pq=PriorityQueue<Integer>(Collections.reverseOrder()); // 내림차순(maxHeap)
System.out.println(pq.peek()); // maxHeap
pq.add(1); //삽입
pq.poll();// 우선순위 제일 높은 값 제거(없으면 null리턴)
//pq.add(new int[] {Math.abs(temp),temp})처럼 배열로 넣어서 우선순위 설정하기
PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if (o1[0] == o2[1])
return o1[1] - o2[1];
return o1[0] - o2[0];
}
});
** etc
Integer.toBinaryString(k) //int k를 2진수 String으로 변경
2차원 행렬 돌리기 (list(map(list,*board)))
public static void rotation_90() {
int n = board.size();
int m = board.get(0).size();
List<List<Integer>> return_board = new ArrayList<>();
for (int i = 0; i < m; i++) {
List<Integer> temp = new ArrayList<>();
for (int j = 0; j < n; j++) {
temp.add(board.get(j).get(i));
}
return_board.add(temp);
}
board = return_board;
}
StringTokenizer() vs split() 차이
split은 데이터를 토큰으로 잘라낸 결과를 배열에 담아서 반환하기 때문에 StringTokenizer 보다 성능이 떨어진다.
그러나 데이터의 양이 많은 경우가 아니라면 별 문제가 되지 않는다
구분자를 split는 정규 표현식으로 구분하고, StringTokenizer는 문자로 받는다.
구분자가 char가 아닌 string 형태도 둘 중 아무거나 사용가능
1. StringTokenizer
2차원 배열을 입력받을 때 원소 하나하나로 접근하고 싶을땐 StringTokenizer를 쓰기도 하지만 여러가지 방법이 있다.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 2. delim을 '%'로 설정.
String str2 = "Wellcome%to%The%Java%HelloWorld";
StringTokenizer st = new StringTokenizer(str2, "%");
System.out.println("- str2의 토큰 개수 : " + st.countTokens());
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
StringTokenizer st = new StringTokenizer(str3, "%/*");
2. split()
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String data[][] = new String[2][4];
//배열로 받아와서 저장하기
data[0] = br.readLine().split(" ");
data[1] = br.readLine().split(" ");
//배열로 받아와서 원소로 접근하여 저장하기
for(int i=0;i<2;i++) {
int j = 0;
for (String v:br.readLine().split(" ")) {
data[i][j] = v;
j++;
}
}
String str = "inpa@tistory@com@super@power";
// 문자열을 자르되, 딱 3번 까지만 자르고 말아라
String[] splitter = str.split("@", 3); // limit 사용
<Output>
StringBuilder를 쓰자
System.out.print <<< 이거 엄청 느림
StringBuilder sb = new StringBuilder();
sb.append("123").append(1).append(" ") ....
System.out.println(sb);
StringBuilder
StringBuilder를 쓰면 메모리 낭비가 되지않음
//String에 + 쓰면서하면 메모리 낭비가 일어난다고함
@Override
public String toString() {
return "Student [major=" + major + "]";
}
public String toString() {
return new StringBuilder(super.toString()).append(department).toString();
}
return new StringBuilder("Person [id=").append(id).append(", name=")
.append(name).append("]").toString();
- 지금 보면 new StringBuilder라는 것은 객체를 만든것인데 따로 변수는 지정하지 않고 객체를 만든것(메모리에 저장)
- return을 해야하니까 toString()을 한 것
- 마지막에 toString()은 StringBuilder안에 내포되어 있는 내장함수
Stream
자바에서는 많은 양의 데이터를 저장하기 위해서 배열이나 컬렉션을 사용하는데
이렇게 저장된 데이터에 접근하기 위해서는 반복문이나 반복자(iterator)를 사용하여 매번 새로운 코드를 작성해야 한다.
하지만 이렇게 작성된 코드는 길이가 너무 길고 가독성도 떨어지며, 코드의 재사용이 거의 불가능함
즉, 데이터베이스의 쿼리와 같이 정형화된 처리 패턴을 가지지 못했기에 데이터마다 다른 방법으로 접근해야만 했습니다.
이러한 문제점을 극복하기 위해서 Java SE 8부터 스트림(stream) API를 도입
스트림 API는 데이터를 추상화하여 다루므로, 다양한 방식으로 저장된 데이터를 읽고 쓰기 위한 공통된 방법을 제공
따라서 스트림 API를 이용하면 배열이나 컬렉션뿐만 아니라 파일에 저장된 데이터도 모두 같은 방법으로 다룰 수 있게 됨
int[][] data = new int[N][2];
for (int i = 0; i < N; i++) {
data[i] = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
}
List<Course> hotCourses = map.keySet().stream()
.sorted((o1, o2) -> (map.get(o1).equals(map.get(o2))) ? Long.compare(o2.getId(), o1.getId()) : Long.compare(map.get(o2), map.get(o1)))
.collect(Collectors.toList());
=
다중조건 정렬
Arrays.sort(data, (o1, o2) -> {
if (o1[1] == o2[1])
return o1[0] - o2[0];
else
return o1[1] - o2[1];
});
// String 비교는
str.compareTo(str2)
'Backend > Java' 카테고리의 다른 글
Java8 (0) | 2022.08.05 |
---|---|
Java 순열과 조합 (0) | 2022.08.04 |
Java 직렬화 (0) | 2022.07.27 |
Java 예외 처리 (0) | 2022.07.26 |
Java Generic, Collection에 대해 (0) | 2022.07.26 |