연산에 사용되는 표시나 기호를 연산자(operator)라고 한다.
연산에는 연산자와 피연산자가 있어야 하며
피연산자는 연산의 대상을 뜻한다.
boolean b = (x == y) ? true : false;
, String s = (x != y) ? "정답" : "오답)
연산자는 산술 > 비교 > 논리 > 대입 순으로 응답값이 결정된다.
단, 괄호로 감싸주면 괄호안의 연산이 최우선순위로 계산된다.
ex) x = 2, y = 9, z = 10일 때 result = x + 10 < y && y < z;
의 값은 false이다.
기타 연산자외에는 기존 Python에서 공부했던 내용이라 편안한 마음으로 강의를 들었다.
단, Python과 달리 Java에서는 몫만 출력된다는 차이점이 있었다.
예를 들어, 5/2를 출력 했을 때의 결과값은 2.5가 아닌 2가 나온다.
2.5를 출력하려면 5.0/2.0으로 나누면 나온다.
기타연산자 중에서는 삼항연산자가 조금 낯설었지만 작성법이 쉬워 금방 익힐 수 있을 것 같다.
비트 연산은 속도가 빠르다고는 하지만, 솔직히 저게 어떤 용도로 쓰이는지 모르겠다. 내가 쓸 일이 있을까..?
그냥 일단 가볍게 훑어만 봤고, 나중에 필요하면 검색하거나 따로 공부하는걸로 하자!
특정 조건에 따라 다른 연산을 수행하고자 할 때 사용한다.
if(조건1) {
조건 1이 true일때 실행
} else if(조건2) {
조건 2가 true일 때 실행
} else {
조건1과 조건2가 false일 때 실행
}
switch (입력 변수){
case 입력값1 : 실행 구문
break;
case 입력값2 : 실행 구문
break;
case 입력값3 : 실행 구문
break;
default: 기본 실행 구문
break;
}
살 것 같다. 조건문이 나를 살렸다.
조금 쉬어가는(?) 느낌으로 들을 수 있었다.
Objects.equals(좌,우)는 두 개의 값을 비교하는 메서드라고 한다.
나중에 메서드들만 따로 정리해둘 필요가 있을 것 같다.
특정 조건에 따라 연산을 반복수행 할 때 사용한다.
반복문 작성시 주의해야 할 점은 무한루프에 빠지지 않도록 조심해야 한다.
for (초기값; 조건문; 증감식) {
조건문이 true일 때 반복수행
}
int i=0
i < 7
i++
코드의 실행순서
초기값 -> 조건문 -> 코드 수행 -> 증감식 -> 조건문 -> 코드 수행 -> 증감식 -> 조건문..(반복)
for (변수정의: 배열명) {
배열의 길이만큼 반복
}
향상된 for문은 배열을 갖고 반복작업을 할 때 주로 사용된다.
기존 for문에 비해 코드가 간결해질 수 있다는 장점이 있지만
배열만 사용 가능하며 배열값을 직접 바꿀수 없다는 단점이 있다.
기존 for문에서 배열을 사용하지 못하는 것은 아니며
컨벤션에 따라 일반적인 for문만 사용하는 곳도 있기 때문에
기존for문이 익숙하지 않다면 옵션정도로만 알아두고 가도 괜찮다.
초기값 //ex) int number = 0;
while(조건문) { //조건문 ex)number < 3
증감식 // ex) number++;
조건문이 true인 동안 반복수행
}
코드에 따라 초기값과 증감식을 작성하지 않아도 반복이 가능하지만 ex)while(true) {}
사용하지 않게 될 때에는 무한루프에 빠질 수 있기에 꼭 유의하여 작성이 필요하다.
do {
처음 실행시 무조건 실행
이후부터는 조건문이 true인 동안 실행
} while (조건문);
기존의 while문과 다른 점은,
첫 실행시 무조건 코드를 한번 실행 후 while의 조건문에 따라 반복을 실행한다.
//사용 예제
while(true){
코드1
if(조건1){
조건코드1
break;
} else if (조건2) {
조건코드2
continue;
}
코드2
}
코드3
조건1이 true일 때의 코드 동작 : 코드1 -> 조건코드1-> 코드3
조건2가 true일 때의 코드 동작 : 코드1 -> 조건코드2 -> 코드1 -> 코드2 ... (반복문종료시 코드3)
for 반복문의 경우, 배열을 사용했던 경우가 많았기 때문에
작성 방식이 조금 낯설었지만 실제 여러 번 코드를 작성해보니 적응이 된 것 같다!
여러개의 변수를 저장할 때 사용하는 변수로
배열의 변수를 선언할 때에는 일반적으로 변수타입[] 변수명
으로 선언하며
선언한 타입과 다른 타입의 변수는 배열에 저장 할 수 없다.
선언 방식
1. 타입[] 배열이름;
2. 타입 배열이름[];
생성 방식
new 타입[배열길이];
선언과 생성을 동시에 진행할 때
1. 타입[] 배열이름 = new 타입[배열길이];
2. 타입[] 배열이름 = {배열요소1, 배열요소2, …};
3. 타입[] 배열이름 = new 타입[]{배열요소1, 배열요소2, …};
배열 요소의 조회 방법
배열[index]
로 배열의 요소를 조회할 수 있다.
ex) array[0]
= array배열의 0번째 인덱스
배열은 참조형 변수로, 실제 값이 아닌 주소값을 가지게 된다.
int[] a = { 1, 2, 3, 4 };
int[] b = a; // 얕은 복사
b[0] = 3; // b 배열의 0번째 순번값을 3으로 수정했습니다. (1 -> 3)
System.out.println(a[0]); // 출력 3 <- a 배열의 0번째 순번값도 3으로 조회됩니다.
대입연산자로 복사하게 될 시 b를 수정하면, a도 함께 수정된다. (a수정시에도 b가 수정된다.)
결국 배열 b와 배열 a는 변수명만 다를 뿐, 원본 값은 같다.
배열 a와 배열 b가 독립적인 값을 가지게 하려면 깊은 복사로 복사해야한다.
깊은 복사를 하는 방법에 대해서는 여러가지 방법이 있다.
반복문을 통해 배열요소를 하나하나 꺼내 새로운 배열에 저장하는 방법
int[] a = { 1, 2, 3, 4 };
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
clone() 메서드를 이용해 복사하는 방법
int[] a = { 1, 2, 3, 4 };
int[] b = a.clone();
clone() 메서드는 가장 쉽게 복사할 수 있지만, 다차원 배열에서는 얕은 복사로 동작하기 때문에
사용시 주의가 필요하다.
Arrays.copyOf() 메서드를 이용해 복사하는 방법
int[] a = { 1, 2, 3, 4 };
int[] b = Arrays.copyOf(a, a.length);
clone() 메서드의 단점을 해결 할 수 있지만 clone 메서드보다는 조금 귀찮다.
파라미터로는 배열, 배열의 길이가 들어가게된다.
배열중에서도 가장 많이 사용하는 배열이다.
자주 사용되는 메서드
메서드 | 응답값 타입 | 설명 |
---|---|---|
length() | int | 문자열의 길이를 반환한다. |
charAt(int index) | char | 문자열에서 해당 index의 문자를 반환한다. |
substring(int from, int to) | String | 문자열에서 해당 범위(from~to)에 있는 문자열을 반환한다. (to는 범위에 포함되지 않음) |
equals(String str) | boolean | 문자열의 내용이 같은지 확인한다. 같으면 결과는 true, 다르면 false가 된다. |
toCharArray() | char[] | 문자열을 문자배열(char[])로 변환해서 반환한다. |
new String(char[] charArr) | String | 문자배열(char[]) 을 받아서 String으로 복사해서 반환한다. |
메서드 사용 예시
String str = "ABCD";
//(1) length
int strLength = str.length();
System.out.println(strLength); //출력값 : 4
//(2) charAt(int index)
char strChar = str.charAt(2);
System.out.println(strChar); //출력값 : C
//(3) substring(int fromIdx, int toIdx)
String strSub = str.substring(0, 3);
System.out.println(strSub); //출력값 : ABC
//(4) equals(String str)
String newStr = "ABCD";
boolean strEqual = newStr.equals(str);
System.out.println(strEqual); //출력값 true
//(5) toCharArray() : String -> char[]
char[] strCharArray = str.toCharArray();
System.out.println(strCharArray[1]); //출력값 B
//(6) char[] -> String -> char
char[] charArray = {'A', 'B', 'C'};
String charArrayString = new String(charArray);
System.out.println(charArrayString); //출력값 ABC
2차원 이상의 배열로, 배열 요소로 또 다른 배열을 가진다.
선언 방식
1. 타입[][] 배열이름;
2. 타입 배열이름[][];
3. 타입[] 배열이름[];
생성 방식
타입 배열이름[행의길이][열의길이] = {
{배열요소[0][0], 배열요소[0][1], …},
{배열요소[1][0], 배열요소[1][1], …},
{배열요소[2][0], 배열요소[2][1], …},
…
};
배열의 마지막 차수의 길이를 지정하지 않고, 가변적으로 생성이 가능하다.
가변배열 예시)
int[][] array = new int[3][];
array[0] = new int[2];
array[1] = new int[4];
array[2] = new int[1];
int[][] array2 = {
{10, 20},
{10, 20, 30, 40},
{10}
}
배열보다 다수의 참조형 데이터를 더 쉽고 효과적으로 처리할 수 있다.
컬렉션의 종류로는 List, Set, Queue, Map 등이 있다.
ArrayList<Integer> intList = new ArrayList<Integer>();
기능
ArrayList<Integer> intList
형태로 선언new ArrayList<Integer>();
intList.add({추가할 값})
intList.set({수정할 순번},{수정할 값})
intList.remove({삭제할 순번})
intList.toStriong()
intList.clear()
예시 코드
//선언 + 생성
ArrayList<Integer> intList = new ArrayList<Integer>();
//추가
intList.add(99); //값 추가
intList.add(22);
intList.add(35);
System.out.println(intList.get(0)); //출력 : 99
//수정
intList.set(2, 30); //2번째 값의 Idx를 30으로 수정
System.out.println(intList.get(1)); //출력 : 30
//삭제
intList.remove(0); //0번째 Idx를 삭제
System.out.println(intList.get(0)); //출력 : 22
//전체삭제
System.out.println(intList.toString());//출력 : [22, 30]
intList.clear();
System.out.println(intList.toString()); //출력 : []
LinkedList<Integer> linkedList = new LinkedList<Integer>();
기본적인 기능은 ArrayList와 동일하지만 차이점으로는 크게 두 가지가 있다.
장점 : 중간에 값을 추가하는 기능
단점 : 값을 나누어 담기 때문에 모든 값을 조회할 때에는 속도가 느림
기능
linkedList.add({추가할 순번}, {추가할 값})
그 외의 기능은 ArrayList와 동일한 방식으로 사용한다.
수직으로 값을 쌓아놓고, 넣었다가 뺀다.
Stack<Integer> intStack = new Stack<Integer>();
최근 저장된 데이터를 나열하고 싶거나, 데이터의 중복 처리를 막고 싶을 때 사용한다.
기능
Stack<Integer> intStack
new Stack<Integer>();
intStack.push({추가할 값})
intStack.peek()
//맨 위의 값 출력intStack.pop()
// 맨 위의 값을 꺼냄. (삭제)예시코드
//선언 및 생성
Stack<Integer> intStack = new Stack<>();
//값 추가
intStack.push(10);
intStack.push(15);
intStack.push(1);
//조회 peek는 값이 사라지지 않는다.
System.out.println(intStack.peek()); //출력 : 1
//크기 구하기
System.out.println(intStack.size()); //출력 : 3
// 값이 없어질 때 까지 출력
while(!intStack.isEmpty()) {
//pop은 꺼내는 순간 값이 사라진다.
System.out.println(intStack.pop()); //출력 : 1, 15, 10
}
생성자가 없는 인터페이스로 LinkedList를 사용한다.
Queue<Integer> intQueue = new LinkedList<>();
기능
Queue<Integer> intQueue
new LinkedList<Integer>();
intQueue.add({추가할 값})
intQueue.peek()
intQueue.poll()
예시코드
//선언 및 생성
Queue<Integer> intQueue = new LinkedList<>();
intQueue.add(1);
intQueue.add(5);
intQueue.add(9);
// peak와 size
System.out.println(intQueue.peek()); //출력 : 1
System.out.println(intQueue.size()); //출력 : 3
//값이 없어질 때 까지 출력
while(!intQueue.isEmpty()) {
System.out.println(intQueue.poll()); //출력 : 1, 5, 9
}
순서가 없고 중복이 없으며 생성자가 없는 인터페이스
Set<Integer> intSet = new HashSet<>();
HashSet, TreeSet 등으로 응용해서 같이 사용이 가능하다.
기능
Set<Integer> intSet
new HashSet<Integer>();
intSet.add({추가할 값})
intSet.remove({삭제할 값})
intSet.contains({포함확인 할 값})
예시코드
//선언 및 생성
Set<Integer> intSet = new HashSet<>();
//값 추가
intSet.add(1);
intSet.add(12);
intSet.add(15);
intSet.add(9);
intSet.add(12);
//전체 출력
for (Integer value: intSet) {
System.out.println(value); //출력 : 1, 9, 12, 15 (중복값은 출력되지 않음)
}
//contains 포함여부 확인
System.out.println(intSet.contains(2)); //출력 : false
System.out.println(intSet.contains(12)); //출력 : true
//삭제
intSet.remove(1);
System.out.println(intSet); //출력 : 9, 12, 15
Key, Value 값을 가지며 Key는 중복되지 않는다.
Python의 Dicionary 구조와 비슷하다.
//선언 및 생성
Map<String, Integer> intMap = new HashMap<>();
//추가
intMap.put("가", 1);
intMap.put("나", 1);
intMap.put("다", 1);
intMap.put("라", 13);
intMap.put("마", 1);
intMap.put("가", 1);
// key 값 전체 출력
for (String key : intMap.keySet()) {
System.out.println(key); //출력값 : 가,나,다,라,마,라 (key는 중복값 허용X)
}
//value 값 전체 출력
for (Integer value : intMap.values()) {
System.out.println(value); //출력값 : 1,1,1,1,13 (Value는 중복값 허용)
}
System.out.println(intMap.get("라")); //출력값 : 13
자료구조 요리 레시피 메모장 만들기
입력값
출력값
ex) 입력 예시
Set
백종원 돼지고기 김치찌개 만들기
돼지고기는 핏물을 빼주세요.
잘익은 김치 한포기를 꺼내서 잘라주세요.
냄비에 들기름 적당히 두르고 김치를 넣고 볶아주세요.
다진마늘 한스푼, 설탕 한스푼 넣어주세요.
종이컵으로 물 8컵 부어서 센불에 끓여주세요.
핏물 뺀 돼지고기를 넣어주세요.
된장 반스푼, 양파 반개, 청양고추 한개를 썰어서 넣어주세요.
간장 두스푼반, 새우젓 두스푼, 고춧가루 두스푼반 넣어주세요.
중불로 줄여서 오래 끓여주세요~!!
마지막에 파 쏭쏭 썰어서 마무리하면 돼요^^
끝
ex) 예시 출력
[ Set 으로 저장된 백종원 돼지고기 김치찌개 만들기 ]
1. 돼지고기는 핏물을 빼주세요.
2. 잘익은 김치 한포기를 꺼내서 잘라주세요.
3. 냄비에 들기름 적당히 두르고 김치를 넣고 볶아주세요.
4. 다진마늘 한스푼, 설탕 한스푼 넣어주세요.
5. 종이컵으로 물 8컵 부어서 센불에 끓여주세요.
6. 핏물 뺀 돼지고기를 넣어주세요.
7. 된장 반스푼, 양파 반개, 청양고추 한개를 썰어서 넣어주세요.
8. 간장 두스푼반, 새우젓 두스푼, 고춧가루 두스푼반 넣어주세요.
9. 중불로 줄여서 오래 끓여주세요~!!
10. 마지막에 파 쏭쏭 썰어서 마무리하면 돼요^^
import java.util.*;
public class Quest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//type별 변수 생성
ArrayList<String> inputStr = new ArrayList<>();
LinkedHashSet<String> inputSet = new LinkedHashSet<>();
Map<Integer, String> inputMap = new HashMap<>();
//데이터 타입과 제목
String dataType = sc.nextLine();
String title = sc.nextLine();
if (Objects.equals(dataType, "List")) {
//List 타입 저장
while(true) {
String input = sc.nextLine();
if (Objects.equals(input, "끝")) {
break;
}
inputStr.add(input);
}
System.out.printf("[ %s %s ]%n",dataType,title);
//List 타입 반목문 출력
for (int i = 1; i <= inputStr.size(); i++) {
System.out.println(i + ". " + inputStr.get(i-1));
}
} else if (Objects.equals(dataType, "Set")) {
while(true) {
String input = sc.nextLine();
if (Objects.equals(input, "끝")) {
break;
}
inputSet.add(input);
}
//힌트부분의 code//
Iterator iterator = inputSet.iterator();
System.out.printf("[ %s %s ]%n",dataType,title);
for (int i=0; i < inputSet.size(); i++) {
System.out.println((i+1) + ". " + iterator.next());
}
} else if (Objects.equals(dataType, "Map")) {
int i = 0;
while(true) {
String input = sc.nextLine();
if (Objects.equals(input, "끝")) {
break;
}
i++;
inputMap.put(i, input);
}
System.out.printf("[ %s %s ]%n",dataType,title);
for (int k = 1; k <= inputMap.size(); k++) {
System.out.println(k + ". "+inputMap.get(k));
}
} else {
System.out.println("잘못된 입력값입니다.");
}
}
}
코드가 정말 난잡하다...!!
Set 부분에선 힌트의 도움을 받았지만
최대한 힌트 없이 혼자 힘으로 작성해보고자 노력한 결과물이다.
코드 정리는 조금 더 배운 뒤 생각해보기로 하고
우선 기능 구현과 배움에 집중하기로 했다.
문제의 코드
//
Scanner sc = new Scanner(System.in);
Set<String> inputSet = new HashSet<>();
while(true) {
String input = sc.nextLine();
if (Objects.equals(input, "끝")) {
break;
}
inputSet.add(input);
}
//힌트부분의 code//
Iterator iterator = inputSet.iterator();
System.out.printf("[ %s %s ]%n",dataType,title);
for (int i=0; i < inputSet.size(); i++) {
System.out.println((i+1) + ". " + iterator.next());
}
//입력 값
Set
제목
과정 1
과정 2
과정 3
과정 4
//출력 값
[ Set 제목 ]
1. 과정 2
2. 과정 1
3. 과정 4
4. 과정 3
정말 의외로 List와 Map은 문제 없이 잘 성공했다.
다만 Set에서 순서가 뒤죽박죽으로 출력되는 문제가 발생했다.
Set은 중복이 없고, 순서가 없는 것으로 알고 있는데
이걸 어떻게 해결해야 할 지 조금 고민이 된다.
코드수정전
Set<String> inputSet = new HashSet<>();
코드수정후
LinkedHashSet<String> inputSet = new LinkedHashSet<>();
HashSet외에도 Treeset / LinkedHashSet이 있다고 한다.
HashSet을 사용했기 때문에 순서를 예측할 수 없는 결과값이 나왔던 것이었다.
LinkedHashSet으로 코드를 수정하자 거짓말처럼 순서대로 잘 출력되기 시작했다.
막연하게 Set은 순서가 없다고만 생각했는데,이번 기회에 좋은 배움이 되었다.