1. 연산자
Java에는 다양한 연산자가 있는데 크게 산술 연산자, 비교 연산자, 논리 연산자, 대입 연산자 등으로 나뉘어진다.
산술연산자에는 +(더하기), -(빼기), *(곱하기), /(나누기), %(나머지), <<(비트 왼쪽 시프트), >>(비트 오른쪽 시프트등이 있다.
System.out.println(4 + 2); // 6
System.out.println(4 - 2); // 2
System.out.println(4 * 2); // 8
System.out.println(4 / 2); // 2
System.out.println(5 / 2); // 2 정수여서 소수점은 버림
System.out.println(2 / 4); // 0
System.out.println(4 % 2); // 0
System.out.println(5 % 2); // 1
System.out.println(3 << 2); // 0011 -> 1100 = 12
System.out.println(3 << 1); // 0011 -> 0110 = 6
// <<은 2^n만큼 곱하기와 같음
// >>은 2^n만큼 나누기와 같음
비교 연산자에는 >(크다), <(작다), >=(크거나 같다), <=(작거나 같다), ==(같다), !=(같지 않다) 등이 있다.
System.out.println(10 > 9); // true
System.out.println(10 >= 9); // true
System.out.println(10 < 9); // false
System.out.println(10 <= 9); // false
System.out.println(10 == 10); // true
System.out.println(10 == 9); // false
System.out.println(10 != 10); // false
System.out.println(10 != 9); // true
논리 연산자에는 &&(AND), ||(OR), !(NOT)등이 있다.
boolean flag1 = true;
boolean flag2 = true;
boolean flag3 = false;
System.out.println("AND-------------------");
System.out.println((5 > 3) && (3 > 1)); // true && true = true
System.out.println((5 > 3) && (3 < 1)); // true && false = false
System.out.println("OR-------------------");
System.out.println((5 > 3) || (3 > 1)); // true && true = true
System.out.println((5 > 3) || (3 < 1)); // true || false = false
System.out.println((5 < 3) || (3 < 1)); // false || false = false
System.out.println("NOT-------------------");
System.out.println(!flag1); // !true = false
System.out.println(!flag3); // !false = false
System.out.println(!(5 == 5)); // !true = false
System.out.println(!(5 == 3)); // !false = true
대입 연산자에는 기본 대입연산자와 복합 대입연산자로 나뉘는데 기본 대입연산자에는 = 이 있고 복합 대입 연산자는 +=, -=, *= 등이 있다.
int number = 10;
number += 2; // number = number + 2
System.out.println(number); // 12
number -= 2; // number = number - 2
System.out.println(number); // 10
number *= 2; // number = number * 2
System.out.println(number); // 20
number /= 2; // number = number / 2
System.out.println(number); // 10
number %= 2; // number = number % 2
System.out.println(number); // 0
System.out.println("----------------");
number++; // number = number + 1 -> number += 1 -> number++
System.out.println(number);
number--; // number = number - 1 -> number -= 1 -> number--
System.out.println(number);
복합 연산자라는 개념도 있는데 ++과 --에 해당된다.
int a = 10;
int b = 10;
int val = ++a + b--; // 11 + 10, ++a는 전치연산자여서 값 증가가 먼저, b--는 후치연산자여서 값 감소가 나중
System.out.println(val); // 11 + 10 = 21, a=11, b=9
복합연산자가 변수 앞에 쓰이면 값의 증감 먼저, 뒤에 쓰이면 값의 증감이 나중이다.
이 외에도 연산자에는 형변환 연산자, 삼항 연산자 등이 있다.
형변환하는 방법은 리터럴 앞에 (자료형)을 붙인다.
int intNumber = 93 + (int)98.8; // 93 + 98 = 191 형 변환으로 소숫점은 버림
System.out.println(intNumber);
double doubleNumber = (double) 93 + 98.8; // 93.0 + 98.8 = 191.8
System.out.println(doubleNumber);
int x = 1;
int y = 9;
boolean b = (x == y) ? true : false; // false ? 앞에 붙은 식이 조건식인데 이 조건식의 결과가
// 참이면 'true'위치에 있는 값을, 거짓이면 'false'위치의 값을 반환한다.
System.out.println(b);
String s = (x != y) ? "정답" : "오답"; // 정답
System.out.println(s);
int max = (x > y) ? x : y; // 9
System.out.println(max);
int min = (x < y) ? x : y; // 1
System.out.println(min);
자료형이 다른 두 변수끼리 연산을 할 때 자료형의 크기가 작은 쪽이 큰 쪽으로(혹은 표현범위가 좁은 쪽이 넓은 쪽으로) 자동으로 형변환 된다.
short x = 10;
int y = 20;
int z = x + y; // short -> int 자동 형변환
long lx = 30L;
long lz = z + lx; // int -> long 자동 형변환
float fx = x; // short, int -> float 자동 형변환
float fy = y;
float fz = z;
System.out.println(lz);
System.out.println(fx);
System.out.println(fy);
System.out.println(fz);
2. 조건문, 반복문
Java에도 여타 언어와 같이 조건문과 반복문이 있다.
조건문에는 if와 switch case문이 있다.
if문은 조건문이 참일때 if문에 붙은 중괄호 안의 코드를 실행한다.
if문의 조건문의 거짓일 때에 맞는 연산을 수행하게 할 때는 else{} 문을 사용하고 if문의 조건문이 거짓일 경우 다른 조건문을 체크해서 참일 때 그에 맞는 연산을 수행하게 할 때는 else if{}문을 사용한다.
boolean flag = true;
if(flag) {
System.out.println("값이 true입니다.");
} else {
System.out.println("값이 false입니다.");
}
int number = 2;
if (number == 1) {
System.out.println("number값은 1입니다.");
} else if (number == 2) {
System.out.println("number값은 2입니다.");
} else {
System.out.println("number값은 모르는 값입니다.");
}
if문은 중첩해서 쓸 수도 있다.
boolean flag = true;
int number = 2;
if (flag) {
System.out.println("flag가 true입니다.");
if (number == 1) {
System.out.println("flag값은 true고 number값은 1입니다.");
} else if (number == 2) {
System.out.println("flag값은 true고 number값은 2입니다.");
} else {
System.out.println("flag값은 true고 number값은 모르겠습니다.");
}
} else {
if (number == 1) {
System.out.println("flag값은 true고 number값은 1입니다.");
} else if (number == 2) {
System.out.println("flag값은 true고 number값은 2입니다.");
} else {
System.out.println("flag값은 true고 number값은 모르겠습니다.");
}
}
switch-case문은 if문에 비해 가독성이 좋다는 특징이 있지만 사용할 수 있는 조건문이 한정되어 있다.
switch(조건에 맞는지 체크할 변수) { case(조건) : 연산...} 과 같이 쓴다.
int month = 8;
String monthString = "";
switch (month) {
case 1:
monthString = "1월";
break;
case 2:
monthString = "2월";
break;
case 3:
monthString = "3월";
break;
case 4:
monthString = "4월";
break;
case 5:
monthString = "5월";
break;
case 6:
monthString = "6월";
break;
case 7:
monthString = "7월";
break;
case 8:
monthString = "8월";
break;
case 9:
monthString = "9월";
break;
case 10:
monthString = "10월";
break;
case 11:
monthString = "11월";
break;
case 12:
monthString = "12월";
break;
default:
monthString = "알 수 없음";
}
System.out.println(monthString);
switch문에 사용되는 변수에는 정수, 문자, 문자열만 된다. 각 케이스의 끝에는 반드시 break;를 붙여줘야 하며 그렇지 않으면 아래에 있는 코드들이 전부 실행된다.
반복문에는 for, while, do-while 등이 있다.
// for문
// (초기값 ; 조건문 ; 증가연산)
for (int i = 0; i < 4; i++) {
System.out.println(i + " 번째 출력!");
}
// 향상된 for문, 배열을 이용해서 for문을 다룰 때 사용
int[] numbers = {3, 6, 9, 12, 15};
for (int number: numbers) {
System.out.print(number + " ");
}
// while문
// while(조건문) { }
int number = 0;
while (number < 3) { //number < 3 동안 반복
number++;
System.out.println(number + "출력!");
}
// do while문, do-while문은 while문 안의 코드가 최소 한번은 실행된다.
int number1 = 4;
do {
System.out.println(number1 + "출력!"); // number1은 이미 4여서 조건이 안맞음에도 한번 실행되서 4출력! 이 출력된다.
} while (number1 < 3);
//break: 가장 가까운 블록의 for문, while문, switch문을 중단
int number2 = 0;
while (number2 < 3) {
number2++;
if (number2 == 2) {
break; // number2가 2가 되면 while문 탈출, 1출력! 출력하고 종료
}
System.out.println(number2 + "출력!!");
}
for (int i = 0; i < 10; i++) {
System.out.println("i: " + i);
if(i == 2) {
break; // i: 2 출력하고 for문 탈출
}
for (int j = 0; j < 10; j++) {
System.out.println("j: " + j);
if (j == 2) {
break; //j: 0, j: 1, j: 2 출력하고 for문 탈출
}
}
}
int number3 = 0;
while (number3 < 3) {
number3++;
if (number3 == 2) {
continue; // number3이 2가 되면 continue 아래는 실행하지 않고 다시 반복문 최상단 코드부터 실행함
}
System.out.println(number3 + "출력!"); // 2출력!은 나오지 않음
}
break는 가장 가까운 블록의 for문, while문, switch문을 탈출한다.
continue는 continue아래의 코드는 실행하지 않고 반복문 최상단 코드부터 다시 실행함
3. 배열
Java에도 같은 자료형의 값을 한번에 묶어놓는 배열이 존재한다.
int[] intArray = new int[3]; // 배열이 선언되고 {0, 0, 0}으로 초기화
boolean[] boolArray = new boolean[3]; // {false, false, false}으로 초기화
String[] stringArray = new String[3]; // {"", "", ""}으로 초기화
int[] intArray2; // 배열이 선언만 됨
intArray2 = new int[3]; // {0, 0, 0}으로 초기화
// 생성한 배열 '순회'(하나씩 조회)하기
// 단건 조회
System.out.println(intArray[1]);
System.out.println("-----------");
// 다건 조회
// length : 길이를 구하는 메서드
for (int i = 0; i < intArray2.length; i++) {
System.out.println(intArray2[i]);
}
배열의 값을 조회할 때는 배열이름[인덱스]처럼 조회한다.
배열을 생성할 때는 new int[3] 같은 방법 말고도 중괄호에 직접 값을 넣어 원하는 값으로 초기화 할 수 있다.
// 배열 초기화
int[] intArr = {10, 20, 30, 40, 50}; // 길이: 5인 배열로 초기화
String[] stringArray = {"a", "b", "c", "d"}; //길이: 4인 배열로 초기화
// for (int i = 0; i < intArr.length; i++) {
// intArr[i] = i; //배열의 각 요소에 값을 입력하기
// }
for (int i = 0; i < intArr.length; i++) {
System.out.println(intArr[i]);
}
System.out.println("-----------");
for (int i: intArr) {
System.out.println(i);
}
Arrays.fill(intArr, 1); // 배열의 모든 요소를 같은 값으로 저장
for (int item: intArr) {
System.out.println(item);
}
배열은 참조형 변수이기에 단순히 대입연산자를 사용한다고 복사가 되진 않는다. 왜냐하면 배열형 변수에 실제로 저장되는 건 배열의 첫 번째 요소의 메모리 주소값이기 때문이다. 따라서 int[] a = new int[5]; int [] b = a를 하면 b에는 a와 같은 주소가 저장되어 사실상 같은 배열을 가리키게 된다.
// 얕은 복사
// 배열 변수에는 배열의 첫 번째 요소의 주소값이 저장됨
int[] a = {1, 2, 3, 4};
int[] b = a; // int 배열 타입의 변수 b에는 a의 주소가 그대로 저장됨
b[0] = 3; // a[0]과 b[0]은 본질적으로 같은 곳을 가리킴
System.out.println(a[0]);
그래서 배열의 값만 같고 완전히 독립된 배열을 만들고 싶으면 for문을 이용해서 한 개씩 복사해서 하나의 요소마다 값을 저장하거나 특별한 메소드를 이용한다.
int[] a = {1, 2, 3, 4};
int[] b = Arrays.copyOf(a, a.length); // a의 값만 그대로 복사해서 새로운곳에 저장함
a[3] = 0;
System.out.println(a[3]);
System.out.println(b[3]);
String도 다른 자료형의 배열들과 똑같이 선언하고 생성할 수 있다.
우리가 흔히 말하는 문자열의 진짜 의미는 문자형 자료의 배열이다. String도 문자열이고 char[]도 문자형 배열이니 문자열이다. 사실 저 둘은 같은 개념이다. 하지만 실질적으론 String을 더 많이 사용하는데 이는 String에는 유용하고 다양한 메소드가 포함되어 있기 때문이다.
String str = "ABCD";
int strLength = str.length(); // 문자열의 길이 반환
System.out.println(strLength);
char strChar = str.charAt(1); // 문자열의 특정 위치의 문자 하나 반환
System.out.println(strChar);
String strSub = str.substring(0, 3); // 시작 지점과 끝 지점을 정해서 정해진 만큼의 문자열을 추출
System.out.println(strSub);
String newStr = "ABCD";
boolean strEqual = newStr.equals(str); // 문자열 간의 비교
System.out.println(strEqual);
char[] strCharArray = str.toCharArray(); // String을 char배열로 변환
Java에서도 2차원 이상의 다차원 배열을 선언할 수 있다.
2차원 배열을 생성하려면 대괄호를 2개 쓰면 된다. 3차원은 3개, n차원은 n개 붙이면 된다.
int[][] array = new int[2][3];
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.println("출력값 => " + i + ", " + j);
array[i][j] = 0;
}
}
2차원 배열의 각 열 배열은 각각 사이즈가 다른 행 배열을 저장하게 할 수도 있다.
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}
}; //중괄호로 배열 원소마다 서로 다른 사이즈의 다차원 배열 초기화도 가능
4. 컬렉션(Collection)
Java에서는 배열보다 더 고급화된 자료구조를 제공하는데 이를 컬렉션이라고 한다. 컬렉션에는 여러 종류가 있다.
ArrayList는 배열처럼 연속된 공간에 데이터를 저장하고 조회할 수 있다. 배열과의 차이점은 크기가 고정되어 생성되는 배열과는 달리 ArrayList는 크기가 가변적으로 늘어난다. 이는 ArrayList에 값이 추가될 때 더 큰 공간이 필요하면 더 큰 공간을 할당 받아서 저장하기 때문이다.
ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(99); // ArrayList의 맨 끝에 값 입력
intList.add(15);
intList.add(3); // {99, 15, 3}
System.out.println(intList.get(1)); // 15 특정 인덱스의 값 읽기
intList.set(1, 10); // {99, 10, 3} 특정 인덱스에 값 입력
System.out.println(intList.get(1)); // 10
intList.remove(0); // {10, 3} 특정 인덱스의 값 제거
System.out.println(intList.get(0)); // 10
System.out.println(intList.toString());
intList.clear(); // ArrayList의 모든 값 제거
System.out.println(intList.toString());
LinkedList는 불연속적인 공간(이하 노드)에 값을 저장하고 각 노드에 다음 노드의 주소를 저장해서 순차적으로 읽을 수 있는 자료구조이다.
LinkedList는 앞에서부터 순차적으로 값을 조회해야 하기에 모든 값을 읽는 속도는 느리지만 연속된 공간을 찾아서 데이터를 저장할 필요가 없기 때문에 중간에 추가하거나 삭제하는 것은 속도가 빠르다.(데이터를 저장할때는 아무공간에나 데이터를 저장하고 데이터의 주소를 앞 뒤로 연결 해주면 끝이다. 삭제는 반대로 앞, 뒤로 인접한 데이터를 서로 이어주고 원래 연결되있던건 지우면 끝이다.)
LinkedList<Integer> linkedList = new LinkedList<Integer>();
linkedList.add(5); // linkedlist 맨 끝에 값 추가
linkedList.add(10);
linkedList.add(3);
System.out.println(linkedList.get(0)); // 0번째 데이터 읽기
System.out.println(linkedList.get(1)); //1번째 데이터 읽기
System.out.println(linkedList.get(2));
System.out.println(linkedList.toString()); // 전체 데이터를 조회하는 속도가 ArrayList보다 느리다
linkedList.add(200);
System.out.println(linkedList.toString()); // 전체 데이터 읽기
linkedList.add(2, 4); //특정 노드에 값을 추가하기
System.out.println(linkedList.toString()); // 데이터를 추가하거나 삭제하는 속도가 빠르다
linkedList.set(1, 30); // 이미 존재하는 노드의 값을 수정하기
System.out.println(linkedList.toString());
linkedList.remove(1); // 원하는 노드 삭제
System.out.println(linkedList.toString());
linkedList.clear(); // linkedlist의 모든 데이터 지우기
System.out.println(linkedList.toString());
Stack은 한쪽 끝에서만 데이터를 입력, 수정, 삭제할 수 있는 자료구조이다. 그래서 Stack은 후입선출(Last In-First Out)의 구조를 가지고 있다.
Stack<Integer> intStack = new Stack<Integer>();
intStack.push(10); // 스택의 끝에 데이터 입력
intStack.push(15);
intStack.push(1);
while(!intStack.isEmpty()) { // 스택에 데이터가 비어있는지 확인
System.out.println(intStack.pop()); // 스택의 데이터를 출력하고 삭제하기
} // 스택은 끝에서만 데이터의 입력, 삭제가 가능
System.out.println(intStack.peek()); // 가장 끝에있는 값 출력
System.out.println(intStack.size()); // 스택의 사이즈 출력
Queue는 한쪽 끝에서는 출력과 삭제만, 반대쪽에서는 입력만 할 수 있는 자료구조이다. 그래서 Queue는 선입선출(First In-First Out)의 성질을 가지고 있다.
Queue<Integer> intQueue = new LinkedList<>(); // queue는 linkedlist의 생성자를 통해 생성
// queue는 클래스가 아닌 인터페이스여서 별도의 생성자가 없다.
intQueue.add(1); //큐 맨 끝에 새로운 값 입력
intQueue.add(5);
intQueue.add(9);
while (!intQueue.isEmpty()) {
System.out.println(intQueue.poll()); //큐 맨 앞의 데이터 출력 후 삭제
}
intQueue.add(1); //큐 맨 끝에 새로운 값 입력
intQueue.add(5);
intQueue.add(9);
intQueue.add(10);
System.out.println(intQueue.peek()); //큐 맨 앞의 데이터 출력
System.out.println(intQueue.size()); //큐의 사이즈 출력
Set은 순서가 없는 데이터의 집합이다. 순서가 없는 대신 중복된 데이터를 허용하지 않는다.
// Set: 순서가 없고 중복이 없는 데이터 집합
// set도 queue처럼 인터페이스여서 생성자가 없음
// Hashset의 생성자를 통해 구현
Set<Integer> intSet = new HashSet<>();
intSet.add(1);
intSet.add(12);
intSet.add(5);
intSet.add(9);
intSet.add(1);
intSet.add(12);
for (Integer value: intSet) {
System.out.println(value); //1 5 9 12
} // 중복값은 입력되지 않음
System.out.println(intSet.contains(2)); // set에 값이 포함된 여부 확인 (boolean으로 리턴)
System.out.println(intSet.contains(5));
Map은 다른 자료구조와는 다르게 key-value구조로 데이터를 저장할 수 있다. 예를 들어 '1-김씨', '2-이씨', '3-박씨' 라는 식으로 데이터가 저장되어 있으면 1을 호출하면 김씨가 나오고, 2를 호출하면 이씨가 나오는 방식이다. Map의 key는 중복을 허용하지 않는다.
// Map : key - value가 한쌍을 이루는 자료구조
// 따라서 key가 중복되면 안됨
Map<String, Integer> intMap = new HashMap<>();
intMap.put("일", 11); // key-value 입력
intMap.put("이", 12);
intMap.put("삼", 13);
intMap.put("삼", 14); // 중복 key
intMap.put("삼", 15);
for (String key: intMap.keySet()) { // keySet() : 키만 추출해서 배열로 만듬
System.out.println(key); // 중복된 키는 표시안됨
}
for (Integer value: intMap.values()) { // values() : 값만 추출해서 배열로 만듬
System.out.println(value); // 키가 중복되면 가장 나중에 입력된 value로 덮어씀
}
System.out.println(intMap.get("삼")); // 특정 키에 해당하는 값 출력
실습 - 컬렉션을 이용해서 요리 레시피 메모장 만들기
import java.util.*;
public class Week02_homework {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String type = sc.nextLine();
String title = sc.nextLine();
String text;
switch (type) {
case "List" :
ArrayList<String> strList = new ArrayList<String>();
while (true) {
text = sc.nextLine();
strList.add(text);
if (text.equals("끝")) {
break;
}
}
System.out.println("[ " + type + " 으로 저장된 " + title + " ]");
for(int i = 0; i < strList.size(); i++) {
System.out.println((i+1) + ". " + strList.get(i));
}
break;
case "Set" :
Set<String> strSet = new HashSet<>();
while (true) {
text = sc.nextLine();
strSet.add(text);
if (text.equals("끝")) {
break;
}
}
Iterator iterator = strSet.iterator();
System.out.println("[ " + type + " 으로 저장된 " + title + " ]");
for (int i = 0; i < strSet.size(); i++) {
int number = i + 1;
System.out.println(number + ". " + iterator.next()); // Map은 순서가 정해지지 않아서 입력한 순서대로 안나옴
}
break;
case "Map" :
Map<Integer, String> strMap = new HashMap<>();
int line = 1;
while (true) {
text = sc.nextLine();
strMap.put(line++, text);
if (text.equals("끝")) {
break;
}
}
System.out.println("[ " + type + " 으로 저장된 " + title + " ]");
for(int i : strMap.keySet()) {
System.out.println(i + ". " + strMap.get(i));
}
}
}
}
'내일배움캠프' 카테고리의 다른 글
Java문법 종합반 3주차 Part1 (0) | 2024.04.25 |
---|---|
계산기 프로젝트 (0) | 2024.04.24 |
Java 문법 종합반 1주차 (0) | 2024.04.22 |
사전캠프 미니미니프로젝트 회고 (0) | 2024.04.19 |
2024-04-19일자 TIL (0) | 2024.04.19 |