계산 하기_연산자 ➕➖✖️➗
계산할 대 계산의 대상이 되는 것이 피연산자이며, 계산의 목적이 되는 것이 연산자이다.
- 연산자 : 덧셈, 뺄셈처럼 계산할 기호 ➕
- 피연산자 : 연산자로 인해 계산되는 숫자 🔢
int x = 5;
int y = 10;
int z = x + y; // 5(피연산자) +(연산자) 10(피연산자) 계산
System.out.println(z); // 출력값 : 15
연산자 종류
산술 연산자 | + - * / % << >> | 사칙 연산과 비트연산 |
비교 연산자 | > < >= <= == != | 크고 작음과 같고 다름을 비교 |
논리 연산자 | && || ! | 그리고(AND)와 또는(OR) 으로 조건을 연결 |
대입 연산자 | = ++ —- | 우변의 값을 좌변에 저장, 연산 복합 대입 |
기타 연산자 | (type) ? : instance of | 형변환 연산자, 삼항 연산자, instance of 연산자 |
산술 연산자
사칙 연산 및 비트 연산을 포함한다.
사칙 연산을 계산한 결과값을 응답한다.
+ 덧셈 - 뺄셈 * 곱셈 / 나눗셈/몫 % 나눗셈/나머지
// 사칙 연산
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(2 + 2 * 2); // 6
System.out.println((2 + 2) * 2); // 8
System.out.println(2 + (2 * 2)); // 6
// 변수를 이용한 연산
int a = 20;
int b = 10;
int c;
// 덧셈
c = a + b;
System.out.println(c); // 30
// 뺄셈
c = a - b;
System.out.println(c); // 10
// 곱셈
c = a * b;
System.out.println(c); // 200
// 나눗셈 (몫)
c = a / b;
System.out.println(c); // 2
// 나눗셈 (나머지) = 나머지 연산
c = a % b;
System.out.println(c); // 0
비교 연산자
값이 크고/작음을 비교하거나 같고/다름을 비교하여 참(true)/거짓(false)값인 boolean 값을 출력한다.
> 크다 < 작다 >= 크거나 같다 <= 작거나 같다 == 같다 != 다르다.
// 비교 연산자 (참이면 true, 거짓이면 false)
System.out.println(10 > 9); // 10 는 9 보다 크다 (참이면 true, 거짓이면 false)
System.out.println(10 >= 9); // 10 는 9 보다 크거나 같다 (true)
System.out.println(10 < 9); // 10 는 9 보다 작다 (false)
System.out.println(10 <= 9); // 10 는 9 보다 작거나 같다 (false)
System.out.println(10 == 10); // 10 는 10 와 같다 (true)
System.out.println(10 == 9); // 10 는 9 과 같다 (false)
System.out.println(10 != 10); // 10 는 10 와 같지 않다 (false)
System.out.println(10 != 9); // 10 는 9 과 같지 않다 (true)
논리 연산자
비교 연산의 결과값으로 받을 수 있는 boolean 값을 연결하는 연산자.
조건을 연결하였을 대 boolean 값들을 조합하여 참(true)/거짓(false) 값인 boolean 값을 출력한다.
&& (AND = 피연산자 모두 참), || (OR=피연산자 둘 중 하나라도 참), ! (피연산자의 반대 boolean 값)
// 논리 연산자
boolean flag1 = true;
boolean flag2 = true;
boolean flag3 = false;
System.out.println(flag1); // true
System.out.println(flag2); // true
System.out.println(flag3); // false
// 피연산자 중 하나라도 true 이면 true
System.out.println(flag1 || flag2); // true
System.out.println(flag1 || flag2 || flag3); // true
// 피연산자 모두 true 이면 true
System.out.println(flag1 && flag2); // true (flag1, flag2 모두 true 라서)
System.out.println(flag1 && flag2 && flag3); // false (flag3은 false 라서)
// And 연산
System.out.println((5 > 3) && (3 > 1)); // 5 는 3 보다 크고, 3 은 1 보다 크다 (true)
System.out.println((5 > 3) && (3 < 1)); // 5 는 3 보다 크고, 3 은 1 보다 작다 (false)
// Or 연산
System.out.println((5 > 3) || (3 > 1)); // 5 는 3 보다 크거나, 3 은 1 보다 크다 (true)
System.out.println((5 > 3) || (3 < 1)); // 5 는 3 보다 크거나, 3 은 1 보다 작다 (true)
System.out.println((5 < 3) || (3 < 1)); // 5 는 3 보다 작거나, 3 은 1 보다 작다 (false)
// System.out.println(1 < 3 < 5); // 불가능한 코드
// 논리 부정 연산자
System.out.println(!flag1); // false (flag1 값의 반대)
System.out.println(!flag3); // true (flag3 값의 반대)
System.out.println(!(5 == 5)); // false
System.out.println(!(5 == 3)); // true
대입 연산자
변수를 바로 연산해서 그 자리에서 저장하는 연산자
기본 대입 연산자 = 와 다른 연산을 함께 쓰는 복합 대입 연산자가 있다. ( += , -= , *= ...)
복합 대입 연산자는 기본 대입 연산자를 심플하게 작성하게 해주는 것이지 기능은 같다.
추가로, +=1 는 ++ 와 동일 (피연산자에 1더해주기)
똑같이 -=1 은 -- 와 동일 (피연산자에 1빼주기)
// 대입 연산자
int number = 10;
number = number + 2;
System.out.println(number); // 12
number = number - 2;
System.out.println(number); // 10
number = number * 2;
System.out.println(number); // 20
number = number / 2;
System.out.println(number); // 10
number = number % 2;
System.out.println(number); // 0
number = number++;
System.out.println(number); // 2
number = number--;
System.out.println(number); // 0
// 복합 대입 연산자
number = 10;
number += 2;
System.out.println(number); // 12
number -= 2;
System.out.println(number); // 10
number *= 2;
System.out.println(number); // 20
number /= 2;
System.out.println(number); // 10
number %= 2;
System.out.println(number); // 0
🔥 대입 연산자 중에 증감 연산자 쓸 때 주의할 점!
++ 또는 -- 를 붙이면 피연산자가 1 더해지거나 1 빼기.
그러나, 피연산자 뒤에 붙이냐, 앞에 붙이냐에 따라서 연산 순서가 달라진다.
연산자
|
연산자 위치
|
기능
|
연산 예
|
++
|
++{피연산자}
|
연산 전에 피연산자에 1 더하기
|
val = ++num; num값+1 후에 val변수에 저장 |
++
|
{피연산자}++
|
연산 후에 피연산자에 1 더하기
|
val = num++; num값을 val변수에 저장 후 num+1
|
—
|
—{피연산자}
|
연산 전에 피연산자에 1 빼기
|
val = -num; num값-1 후에 val변수에 저장
|
—
|
{피연산자}—
|
연산 후에 피연산자에 1 빼기
|
val = num-; num값을 val변수에 저장 후 num-1
|
*연산을 직접 할 때도 마찬가지로 선/후 작용이 나뉜다.
// 대입 증감 연산자
public class Main {
public static void main(String[] args) {
int a = 10;
int b = 10;
int val = ++a + b--; // a 는 연산전에 +1, b 는 연산후에 -1
System.out.println(a); // 11
System.out.println(b); // 9
System.out.println(val); // 21
// 11 + 9 가 왜 21이 나오는거죠??
// 그 이유는
// a 는 val 연산전에 ++ 가 수행되어서 11로 연산되었지만
// b 는 val 연산후에 -- 가 수행되어서 기존값이 10으로 연산된 후 -- 가 수행
// 따라서 연산된 a값인 11과 연산되기전 b값인 10이 더해져서 21이 됨!
int c = a--; // c 에 a 값 대입 후 a-1 (즉, a=10, c=11)
int d = ++b; // b 값 +1 후에 d 에 대입 (즉, b=10, d=10)
int val = c-- * ++d; // c 는 연산후에 -1, d 는 연산전에 +1
System.out.println(a); // 10
System.out.println(b); // 10
System.out.println(c); // 11
System.out.println(d); // 10
System.out.println(val); // 11 * 11 = 121
// 11 * 10 이 왜 121이 나오지?
// 그 이유는
// c 는 val 연산후에 -- 가 수행되어서 기존값이 11로 연산된 후 -- 가 수행되었지만
// d 는 val 연산전에 ++ 가 수행되어서 11로 연산된다.
// 따라서 연산전 a값인 11과 연산된 b값인 11이 곱해져서 121이 된다!
}
}
기타 연산자
형변환 연산자
괄호 안에 변환할 타입을 넣으면 피연사자의 타입이 변경된다.
// 형변환 연산자
int intNumber = 93 + (int) 98.8; // 93 + 98
double doubleNumber = (double) 93 + 98.8; // 93.0 + 98.8
삼항 연산자
비교 연산의 결과값에 따라 응답할 값을 직접 지정할 수 있는 연산자.
삼항 연산자는 3가지 피연산자가 존재 = 삼항 연산자. (조건/참결과/거짓결과)
(조건) ? (참 결과) : (거짓 결과)
// 삼항 연산자
int x = 1;
int y = 9;
boolean b = (x == y) ? true : false;
System.out.println(b); // false
String s = (x != y) ? "정답" : "땡";
System.out.println(s); // 땡
int max = (x > y) ? x : y;
System.out.println(max); // 9
int min = (x < y) ? x : y;
System.out.println(min); // 1
instance of 연산자
피연산자가 조건에 명시된 클래스의 객체인지 비교하여 참/거짓을 응답해주는 연산자.
(객체명) instance of (클래스명)
연산자 우선순위
산술 > 비교 > 논리 > 대입 순
우선순위에 따라 최정적인 응답 값이 결정.
괄호로 감싸주면 괄호 안의 연산이 최우선 순위로 계산
// 연산자 우선순위
int x = 2;
int y = 9;
int z = 10;
boolean result = x < y && y < z; // <,> 비교연산자 계산 후 && 논리 연산자 계산
System.out.println(result); // true
result = x + 10 < y && y < z; // +10 산술연산자 계산 후 <,> 비교연산자 계산 후 && 논리 연산자 계산
System.out.println(result); // false
result = x + 2 * 3 > y; // 산술연산자 곱센 > 덧셈 순으로 계산 후 > 비교연산자 계산
System.out.println(result); // false (8>9)
result = (x + 2) * 3 > y; // 괄호안 덧셈 연산 후 괄호 밖 곱셈 계산 후 > 비교연산자 계산
System.out.println(result); // true (12>9)
산술 변환
연산 전에 피연산자의 타입을 일치시킨다. 두 피연산자의 타입을 같게 일치시킨다. (둘 중에 저장공간 크기가 더 큰 타입으로 일치)
- 피연산자의 타입이 int 보다 작은 short 타입이면 int로 변환
- 피연산자의 타입이 long 보다 작은 int, short 타입이면 Long으로 변환
- 피연산자의 타입이 float보다 작은 long, int, short 타입이면 float으로 변환
- 피연산자의 타입이 double 보다 작은 float, long, int, short 타입이면 double으로 변환
- 이처럼, 변수 여러 개를 연산했을 때 결과값은 피연산자 중 표현 범위가 가장 큰 변수 타입을 가지게 된다.
// 산술변환
public class Main {
public static void main(String[] args) {
short x = 10;
int y = 20;
int z = x + y; // 결과값은 더 큰 표현타입인 int 타입의 변수로만 저장 가능.
long lx = 30L;
long lz = z + lx; // 결과값은 더 큰 표현타입인 long 타입의 변수로만 저장 가능.
float fx = x; // 결과값은 더 큰 표현타입인 float 타입의 변수로만 저장 가능.
float fy = y; // 결과값은 더 큰 표현타입인 float 타입의 변수로만 저장 가능.
float fz = z; // 결과값은 더 큰 표현타입인 float 타입의 변수로만 저장 가능.
System.out.println(lz);
System.out.println(fx);
System.out.println(fy);
System.out.println(fz);
}
}
비트 연산
Bit는 0, 1 둘 중의 하나의 값만 저장하는 컴퓨터가 저장 가능한 가장 작은 단위
Bit가 제일 작은 단위라서 계산이 제일 빠름 -> 비트 연산으로 자릿수를 옮길 수 있다.
<< 왼쪽으로 자릿수 옮기기
>> 오른쪽으로 자릿수 옮기기
0, 1은 2진수 값이기 때문에
1. 자릿수를 왼쪽으로 옮기는 횟수만큼 2의 배수로 곱셈이 연산되는 것과 동일
2. 자릿수를 오른쪽으로 옮기는 횟수만큼 2의 배수로 나눗셈이 연산되는 것과 동일
// 비트 연산
// 참고, 3의 이진수값은 11(2) 입니다. 12의 이진수값은 1100(2) 이다.
// (2) 표기는 이 숫자가 이진수값이라는 표식
System.out.println(3 << 2);
// 3의 이진수값인 11(2) 에서 왼쪽으로 2번 옮겨져서 1100(2) 인 12값이 된다.
System.out.println(3 >> 1);
// 3의 이진수값인 11(2) 에서 오른쪽으로 1번 옮겨져서 1(2) 인 1 값이 된다.
📧 문맥 만들기 (조건문, 반복문)
Java 프로그래밍에서 특정 조건에 따라 다른 연산을 수행하고 싶을 때 조건문을 사용
또는, 특정 조건에 따라 반복해서 동일한 연산을 수행하고 싶을 때 반복문을 사용
if (조건)
특정 조건에 따라 다른 연산을 수행하고 싶을 때, 사용하는 문맥
기본적인 조건에 따른 연산을 수행하기 위해 if(조건) { 연산 } 형태로 사용.
if의 소괄호() 안의 조건 boolean 값 true 값을 만족하면 중괄호 {} 안의 연산을 수행
// 조건문
boolean flag = true;
if (flag) {
System.out.println("flag 값은 true 입니다."); // flag 값은 true 입니다. 출력
}
if(조건)-else
if문 조건이 거짓인 경우에 따른 연산을 수행하기 위해 else { 연산 } 형태로 사용.
if 의 소괄호 () 안의 조건이 boolean 값 false를 만족하면 else의 중괄호 {} 안의 연산을 수행.
// 조건문 with else
boolean flag = false;
if (flag) {
System.out.println("flag 값은 true 입니다."); // 미출력
} else {
System.out.println("flag 값은 false 입니다."); // flag 값은 false 입니다. 출력
}
if (조건)-else if(조건)
if문 조건이 거짓일 경우에 다시 한 번 다른 조건으로 체크해서 참일 경우, 연산을 수행하기 위해
else if(조건) { 연산 } 형태로 사용
조건문 with else if
// 조건문 with else if
int number = 2;
if (number == 1) {
System.out.println("number 값은 1 입니다."); // 미출력
} else if (number == 2) {
System.out.println("number 값은 2 입니다."); // number 값은 2 입니다. 출력
} else {
System.out.println("number 값은 모르는 값입니다."); // 미출력
}
중첩 if(조건)
if 문에 else, else if로 해결할 수 없는 복잡한 조건이 잇다.
이럴 때 중첩해서 if문 또는 else if문 또는 else 문 안에 if 문을 넣을 수 있다.
중첩 조건문
// 중첩 조건문
boolean flag = true;
int number = 2;
if (flag) {
if (number == 1) {
System.out.println("flag 값은 true, number 값은 1 입니다."); // 미출력
} else if (number == 2) {
System.out.println("flag 값은 true, number 값은 2 입니다."); // flag 값은 true, number 값은 2 입니다. 출력
}
} else {
if (number == 1) {
System.out.println("flag 값은 false, number 값은 1 입니다."); // 미출력
} else if (number == 2) {
System.out.println("flag 값은 false, number 값은 2 입니다."); // 미출력
}
}
switch (피연산자) / case (조건)
switch문은 case문과 함게 사용하며 if문 보다 좀 더 가독성이 좋은 조건문 표현식이다.
switch(피연산자) { case (조건): (연산) }
switch 피연산자 가 case 조건을 만족하면 case: 뒤에 명시되어 있는 연산을 수행한다.
case (조건): (연산)은 여러 개를 설정할 수 있다!!!
- 각 case의 연산문 마지막에는 break;를 꼭 넣어줘야 한다.
- break; 문 해당 case의 연산문이 끝났더는 것을 알려주어 switch 문을 종료시킨다.
만약 case의 연산문 마지막에 break; 를 안 넣어주면 어떻게 될까..?
- case의 연산문이 안 끝났기 때문에 switch문 블럭이 끝날 때까지 전부 실행된다.. ㅠㅠ
switch문 중괄호 안의 제일 마지막에 default: (연산)을 명시해 주어
case 조건들이 모두 만족하지 않을 때 수행할 연산을 정해주어야 한다.
- default: (연산) 은 아무것도 만족하지 않을 때 수행하는 것이 아닐, 없다면 생략해도 된다.
switch/case 문 예시
// 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); // 8월 출력
if 문과 switch 문
우리가 배운 if문과 switch 문 모두 조건문을 구현하는 문맥.
차이점1. 복합 조건
- if는 복합 조건을 지원 : 괄호 안에 조건 여러 개를 지정하여 조건문을 수행할 수 있다.
- switch 문은 피연산자 한 개에 대한 조건만 지원.
차이점2. 코드 중복
- if 문은 상대적으로 코드 중복이 많다.
- switch 문은 코드 중복이 적다.
if문 & switch문
// if vs switch
// switch 문 실습코드를 if 문으로 바꾸기
// switch
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); // 8월 출력
// if 로 변환
if (month == 1) {
monthString = "1월";
} else if (month == 2) {
monthString = "2월";
} else if (month == 3) {
monthString = "3월";
} else if (month == 4) {
monthString = "4월";
} else if (month == 5) {
monthString = "5월";
} else if (month == 6) {
monthString = "6월";
} else if (month == 7) {
monthString = "7월";
} else if (month == 8) {
monthString = "8월";
} else if (month == 9) {
monthString = "9월";
} else if (month == 10) {
monthString = "10월";
} else if (month == 11) {
monthString = "11월";
} else if (month == 12) {
monthString = "12월";
} else {
monthString = "알 수 없음";
}
System.out.println(monthString); // 8월 출력
계속🔁 : 반복문 - for, while, do-while
for 문
특정 조건에 따라 연산을 반복해서 수행하고 싶을 때 사용하는 문맥
for (초기값; 조건문; 증가연산) { (연산) } 형태로 사용
특정 조건은 초기값과 조건문을 통해 정의한다.
반복할 때마다 값을 증가시키려면 증가연산을 정의한다.
초기값이 조건문을 만족할 때까지 (연산)을 수행하면서 회차마다 증가연산을 수행.
for문
// for 문
for(int i=0; i < 4; i++) { // 변수 i 값은 0 ~ 3 까지 반복
System.out.println(i + "번째 출력"); // i 변수와 문자열 합치기
}
// 출력
0번째 출력
1번째 출력
2번째 출력
3번째 출력
향상된 for 문
for 소괄호 안에 값이 3개나 들어가기 때문에 이걸 2개로 줄여주는 방법이 향상된 for문이다.
향상된 for문은 연속된 변수 목록을 출력할 때 쓰인다.
for (변수 타입 변수 명 : 목록변수) { (연산) } 형태로 사용한다.
변수 타입과 변수 명은 for 문 안에서 연산을 수행할 변수를 정의한다.
목록변수는 3,6,9,12,15 처럼 값 여러개를 하나의 변수로 저장하고 싶을 때 사용한다.
향상된 for 문
// 향상된 for 문
int[] numbers = {3,6,9,12,15};
for(int number: numbers) {
System.out.print(number + " ");
}
// 출력
3 6 9 12 15
// 만약 기존 for 문으로 구현한다면?
int[] numbers = {3,6,9,12,15};
for(int i = 0; i < numbers.length; i++) { // 배열에 .length 를 붙이면 길이값이 응답된다.
System.out.println(numbers[i]);
}
// 출력
3 6 9 12 15
while 문, do-while문
for 문과 동일학세 특정 조건에 따라 연산을 반복해서 수행하고 싶을 때 사용하는 문맥.
다만, 초기값 없이 조건문만 명시하여 반복.
while(조건문) { (연산) } 형태로 사용한다. (while 문)
위 처럼 while 문으로 사용하면 조건문을 만족해야지만 연산이 반복 수행.
한 번 반복할 때마다 조건문을 체크해서 조건문이 불만족(false)이면 반복을 중단.
do { (연산) } while(조건문) 형태로도 사용한다. (do-while문)
위처럼 do-while 문으로 사용하면 최초 1회 연산 수행 후 조건문을 체크하여 더 반복할 지 결정한다.
반복하게 되면 그 이후에는 한 번 반복할 때마다 조건문을 체크하여 조건문이 불만족(false) 이면 반복을 중단한다.
while문, do-while문
// while 문
int number = 0;
while(number < 3) {
number++;
System.out.println(number + "출력");
}
// 출력
1출력
2출력
3출력
// do-while 문
int number = 4;
do {
System.out.println(number + "출력");
} while(number < 3); // 연산을 한번 수행 후 조건문 체크
// 출력
4출력
break 명령
break; 명령을 호출하면 가장 가가운 블럭의 for문 또는 while문을 중단. (도는switch)
반복문 안에서 break; 형태로 사용.
// break 명령
int number = 0;
while(number < 3) {
number++;
if (number == 2) {
break; // 2일때 반복 중단
}
System.out.println(number + "출력");
}
// 출력
1출력
// break 명령 범위
for (int i = 0; i < 10; i++) {
System.out.println("i: " + i);
if (i == 2) {
break; // i 가 2일때 가장 바깥 반복문이 종료됩니다.
}
for (int j = 0; j < 10; j++) {
System.out.println("j: " + j);
if (j == 2) {
break; // j 가 2일때 가장 안쪽 반복문이 종료됩니다.
}
}
}
// 출력
i: 0 // 바깥 반복문 부터 수행 시작
j: 0 // 안쪽 반복문 1회차 수행
j: 1
j: 2 // j 가 2일때 안쪽 반복문 break;
i: 1 // 바깥 반복문은 아직 break; 호출이 안됬으므로 다음 반복수행
j: 0 // 안쪽 반복문 2회차 수행
j: 1
j: 2 // j 가 2일때 안쪽 반복문 두번째 break;
i: 2 // i 가 2일때 바깥 반복문도 break; 호출되어 종료
continue 명령
for문 또는 while문에서 해당 순서를 패스하고 싶을 때 continue 명령을 사용한다.
반복문 안에서 continue; 형태로 사용.
// continue 명령
int number = 0;
while(number < 3) {
number++;
if (number == 2) {
continue; // 2일때 반복 패스
}
System.out.println(number + "출력");
}
// 출력
1출력
3출력
조건문, 반복문 익숙해지기.
// 구구단 생성기
for (int i = 2; i <= 9; i++) { // 구구단 첫번째 지수 i
for (int j = 2; j <= 9; j++) { // 구구단 두번째 지수 j
System.out.println(i + "곱하기" + j + "는" + (i * j) + "입니다.");
}
}
// 출력
2곱하기2는4입니다.
2곱하기3는6입니다.
2곱하기4는8입니다.
... 중략 ...
9곱하기8는72입니다.
9곱하기9는81입니다.
선택적 구구단 생성기
// 선택적 구구단 생성기
Scanner sc = new Scanner(System.in);
int passNum = sc.nextInt(); // 출력제외할 구구단수 값
for (int i = 2; i <= 9; i++) {
if (i == passNum) {
continue;
}
for (int j = 2; j <= 9; j++) {
System.out.println(i + "곱하기" + j + "는" + (i * j) + "입니다.");
}
}
// 입력
2
// 출력 - 입력값인 2단은 건너띄고 구구단 출력
3곱하기2는6입니다.
3곱하기3는9입니다.
3곱하기4는12입니다.
... 중략 ...
9곱하기8는72입니다.
9곱하기9는81입니다.
🗳 분류통으로 정리하기 (배열🗂)
Java 프로그래밍에서 여러 개의 변수를 분류통 같은 곳에 모아서 저장하고 싶을 때 기본적으로는 “배열”이라는 변수에 저장(표현).
분류통🗳️이라고 표현한 이유는 여러 개의 값들을 한꺼번에 넣거나 하나씩 넣을 수도 있고, 꺼낼 때는 하나씩 꺼낼 수 있기 때문인데..
즉, 변수들을 담을 수 있는 분류통🗳️ 중에서 가장 기본이 되는 분류통이 배열이다. 배열 = []
👉참고로, 분류통🗳️은 자료구조라는 이름으로 불린다.
1. 배열
선언 (🗳️[ ])
int 와 같은 기본형 변수는 1개의 값만 변수에 저장할 수 있다면 int[] 와 같은 배열형 변수는 여러 개를 변수에 저장할 수 있다.
- 여러 개를 하나의 변수에 넣어놓고 들고 다니거나 하나씩 꺼내서 쓸 수 있다는 점에서 분류통🗳️의 개념과 비슷하다.
- 단, 하나의 배열형 변수에는 같은 타입의 변수만 담을 수 있다. (=김치통에는 김치만!)
- 한 번에 많은 양의 데이터를 다루거나 계산할 때 사용
- 배열은 영어로 Array
- 선언 방법은 아래 2가지 방법이 있습니다.
1. 타입 [ ] 변수;
ex) int[ ] intArrray;
2. 타입 변수[ ];
ex) int intArray[ ];
// 배열 선언
// 일반적인 선언방식
int[] intArray; // 정수 배열
long[] longArray;
double[] doubleArray; // 실수 배열
char[] charArray; // 문자 배열
String[] stringArray; // 문자열 배열
// 배열 선언
// 2번째 선언방식
int intArray[]; // 정수 배열
long longArray[];
double doubleArray[]; // 실수 배열
char charArray[]; // 문자 배열
String stringArray[]; // 문자열 배열
생성 (new 🗳️[ ])
배열(Array)는 참조형 변수들처럼 new 명령을 통해서 생성하며, 대괄호[ ] 안에 크기를 지정해 준다.
- 분류통🗳️을 만들 때 new 명령어로 생성하고 분류통에 몇 개를 담을지 미리 정의해 준다고 생각
- ☝️주의할 점은 사이즈를 지정해서 생성된 분류통은 각 칸마다 순번이 있다는 걸 기억!
- 순번은 0부터 시작하기 때문에 8개 사이즈의 분류통이라면 0번~7번까지 있다.
- 아래 그림에서 분류통 그림 아래에 보이는 **[숫자]**가 순번이다.
- 추가로, 분류통(배열)은 생성될 때 각 타입별 초기값으로 초기화되어 채워진다.
예를 들어, int 0, boolean은 false, String은 null 값과 같은 초기값이 정해져있다.
참조형 변수이기 때문에 실제 값을 담지 않고 실제 값의 주소값을 저장하고 있다.
// 배열 생성
//배열 생성후 초기화하면 배열의 주소가 할당된다.
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}
순회 (🗳️[ i ])
배열(분류통 🗳️) 안에 담겨있는 변수를 하나씩 꺼내서 사용하는 것을 순회라고 한다.
배열의 값을 하나 뽑아서 조회하기.
배열(분류통 🗳️)에는 순번이 있고 해당 순번을 통해 하나의 값을 조회할 수 있다.
// 배열 단건조회
int[] intArray = new int[3]; // 모두 0으로 초기화된 사이즈8의 배열 생성
// 배열에서 2번쨰 순번의 값을 출력해본다. (0부터 순번이 시작하므로 2번째 순번은 1)
System.out.println(intArray[1]);
// 출력
0
배열을 순회하는 방법은 반복문 사용이 가장 일반적이다.
반복문 안에서 단건 조회했던 것처럼 대괄호 [ ] 안에 반복문 순번 값 i 를 넣어준다.
//길이가 8인 정수배열 선언
int[] intArray = new int[3];
// 배열이 초기화된 값을 출력해본다.
for(int i=0; i<intArray.length; i++) { // .length 는 배열의 길이
System.out.println(intArray[i]);
}
// 출력
0
0
0
.length() 메서드
배열이 지원하는 메서드로써 해당 배열이 길이 값을 응답해준다.
배열의 길이는 처음에 선언한 크기를 가진다.
초기화 (🗳️ = { ... } )
배열(분류통)을 초기화
- 중괄호 { } 를 사용해서 초기화
- 반복문 for문을 사용해서 초기화 (또는 향상된 for문)
- Array.fill 메소드를 사용해서 초기화
Array 클래스는 Java에서 기본으로 제공하는 메소드가 담긴 클래스
// 배열 초기화
import java.util.Arrays; // Arrays 클래스를 import 하자!
public class Main {
public static void main(String[] args) {
//1. 배열에 특정값 대입하며 선언
int[] intArray = {1, 2, 3, 4, 5};
String[] stringArray = {"a", "b", "c", "d"};
//2-1. for문을 통해 값을 대입
for (int i = 0; i < intArray.length; i++) {
intArray[i] = i;
}
//2-2. 향상된 for문을 통한 배열 출력
for (int i : intArray) {
System.out.print(i); // 01234
}
System.out.println(); // 줄바꿈
//3. 배열의 주소를 모두 같은값으로 초기화
Arrays.fill(intArray, 1);//배열의 모든 값을 1로 초기화
for (int i : intArray) {
System.out.print(i); // 11111
}
}
}
// 출력
01234
11111
복사 (🗳️ .clone( ) )
얕은 복사
배열 변수 간에 대입 연산자 =를 사용해서 복사를 하면 주소값만 복사되고 실제 값은 2개로 유지됨.
주소값만 복사된다?
- 변수명은 서로 다르지만 같은 값을 보고 있다.
ex) 계정 하나로 iphone 1, PC 1개에 로그인 .. 그러나 실제 값은 1개다.
// 얕은 복사
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으로 조회된다.
깊은 복사
얕은 복사처럼 가자 복사가 아니라 진짜 새로운 배열을 똑같이 만들고 싶을 때 깊은 복사를 한다.
깊은 복사는 결국 실제 값을 가지고 있는 배열의 기본형 값을 꺼내서 복사해주면 된다.
반복문 for 문을 통해서 하나씩 꺼내서 복사해주는 방법과 여러 메서드를 사용하는 방법이 있다.
// 깊은 복사
int[] a = { 1, 2, 3, 4 };
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[i] = a[i]; // 깊은 복사
}
b[0] = 3; // b 배열의 0번째 순번값을 3으로 수정했습니다. (1 -> 3)
System.out.println(a[0]); // 출력 1 <- 깊은 복사를 했기때문에 a 배열은 그대로.
// 깊은 복사 메서드
// 1. clone() 메서드
int[] a = { 1, 2, 3, 4 };
int[] b = a.clone(); // 가장 간단한 방법
// 하지만, clone() 메서드는 2차원이상 배열에서는 얕은 복사로 동작한다!!
// 깊은 복사 메서드
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
// 2. Arrays.copyOf() 메서드
int[] a = { 1, 2, 3, 4 };
int[] b = Arrays.copyOf(a, a.length); // 배열과 함께 length값도 같이 넣어주기
}
}
2. String 배열 📮
선언, 생성, 초기화
String 배열 선언과 생성
// String 배열을 아래와 같이 선언과 생성할 수 있다.
String[] stringArray = new String[3];
String 배열 초기화
// 선언 후 하나씩 초기화 할 수 있다.
String[] stringArray = new String[3];
stringArray[0] = "val1";
stringArray[1] = "val2";
stringArray[2] = "val3";
// 선언과 동시에 초기화 할 수 있다.
String[] stringArray1 = new String[]{"val1", "val2", "val3"};
String[] stringArray2 = {"val1", "val2", "val3"};
String 기능 활용 (=char 배열)
문자열 = 문자 배열
문자 배열은 연속된 문자인데… 이건 문자열이랑 같은 것 아닌가???
정답! char 배열은 “문자 배열”이고 String 은 문자열이다.
수식으로 표현
- String = char[]
👀 기본형 변수와 참조형 변수의 차이!
기본형 변수는 소문자로 시작하고 참조형 변수는 대문자로 시작한다.
👉 다시 한번 리마인드! 참조형 변수는 실제 값의 주소값을 저장하고 있는 변수
- String 은 char 배열과 같아 둘 다 문자열을 저장할 수 있다.
- String을 더 많이 쓰는 이유는 참조형 변수가 더 많은 기능을 가지고 있기 때문!
- char 배열에 없는 String만 가지고 있는 기능
메서드
|
응답값 타입
|
설명
|
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 기능 활용하기
String str = "ABCD";
// length()
int strLength = str.length();
System.out.println(strLength); // 4 출력
// charAt(int index)
char strChar = str.charAt(2); // 순번은 0부터 시작하니까 2순번은 3번째 문자를 가리킨다.
System.out.println(strChar); // C 출력
// substring(int from, int to)
String strSub = str.substring(0, 3); // 0~2순번까지 자르기. (3순번은 제외)
System.out.println(strSub); // ABC 출력
// equals(String str)
String newStr = "ABCD"; // str 값과 같은 문자열 생성
boolean strEqual = newStr.equals(str);
System.out.println(strEqual); // true 출력
// toCharArray()
char[] strCharArray = str.toCharArray(); // String 을 char[] 로 변환
// 반대로 char[] 를 String로 변환하는 방법
char[] charArray = {'A', 'B', 'C'};
String charArrayString = new String(charArray); // char[] 를 String 으로 변환
3. 다차원 배열🗳🗳
2차원 배열(2열 배열), 순회
- 1열로 구성된 분류통🗳️을 배열 = 1차원 배열
- 1열 배열을 위로 쌓으면 2열 배열, = 2차원 배열🗳️🗳️
선언
2차원 배열을 선언할 때 1차원 배열에 대괄호를 하나 더 추가.
- int[ ] [ ] array
- int array [ ] [ ]
- int[ ] array[ ]
생성
2차원 배열을 생성할 대도 대괄호를 하나 더 추가.
int [ ] [ ] array = new int[ ] [ ];
초기화
1. 중괄호를 사용해 선언과 동시에 초기화
// 중괄호를 사용해 초기화
int[][] array = {
{1, 2, 3},
{4, 5, 6}
};
2. 선언/생성 이후 반복문을 통해 초기화
// 반복문을 통한 초기화
int[][] array = new int[2][3]; // 최초 선언
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
arr[i][j] = 0; // i, j 는 위 노란색 네모박스 안에있는 숫자를 의미하며 인덱스 라고 부른다.
}
}
가변 배열
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}
};
2차원 배열 이상의 다차원 배열 이해
- 2차원 배열 외에도 3차원, 4차원 등..이 있지만 거의 대부분 3차원까지만 사용하는 경우가 많다.
- 3차원 배열?
- 3차원 배열 선언은 2차원 배열 생성에 괄호를 하나 더해주면 된다.
- ex. int[ ][ ][ ] multiArrary
- 초기화할 때는 중괄호를 더 추가하면 된다.
- {{{배열원소1}, {배열원소2}}, {{배열원소3}}} 와 같은 형태로 초기화가 가능
- 3차원 배열 선언은 2차원 배열 생성에 괄호를 하나 더해주면 된다.
// 3차원 배열의 이해
// 중괄호 3개를 써서 3차원 배열 초기화
int[][][] MultiArray = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}};
다차원 배열 조회
- 2차원 배열 조회할 때는 2차원 인덱스를 가진만큼 2중 반복문을 통해 출력할 수 있다.
- 2중 반복문을 통해 가변 배열도 출력 가능
// 가변 2차원 배열 조회
int[][] array = {
{10, 20, 30},
{10, 20, 30, 40},
{10, 20}
};
for (int i = 0; i < array.length; i++) { // 1차원 길이
for (int j = 0; j < array[i].length; j++) { // 2차원 길이
System.out.println(array[i][j]); // 2중 반복문으로 i, j 인덱스 순회
}
}
// 출력
10
20
30
10
20
30
40
10
20
예제 1. 최대값 구하기
// 최대값 구하기
int[] arr = { 3, 2, 1, 5, 1 };
// 최대값 초기값 세팅
int max = arr[0];
// 최대값 구하기
for (int num : arr) {
if (num > max) { // 반복문 돌면서 나(max)보다 값이 작으면 저장
max = num;
}
}
// 최대값 5 출력
System.out.println(max);
예제 2. 최소값 구하기
// 최소값 구하기
int[] arr = { 3, 2, 1, 5, 1 };
// 최소값 초기값 세팅
int min = arr[0];
// 최소값 구하기
for (int num : arr) {
if (num < min) { // 반복문 돌면서 나(min)보다 값이 작으면 저장
min = num;
}
}
// 최소값 1 출력
System.out.println(min);
🗳참조형 분류통으로 정리하기 (컬렉션🧬)
Java 프로그래밍에서는 배열🗳️을 더 고도화 시켜서 컬렉션🧬이라는 이름으로 참조형 분류통(자료구조)를 제공하고 있다.
컬렉션은 참조형 변수만 저장함으로써 여러 기능을 많이 제공한다.
컬렉션🧬은 여러 가지 종류가 있고, 이러한 컬렉션🧬들은 데이터를 넣고 빼는 방법이 각자 다르기 때문에 용도에 맞게 사용.
- 컬렉션🧬 이해하기
- Java에서 컬렉션🧬 은 배열보다 다수의 참조형 데이터를 더 쉽고 효과적으로 처리할 수 있는 기능을 많이 가지고 있다.
- 컬렉션🧬 기능 : 크기 자동 조정/ 추가/ 수정/ 삭제/ 반복/ 순회/ 필터/ 포함 확인 등….
- 컬렉션🧬 종류
- Collection에는 List, Set , Queue , Map 이 있다.
- List : 순서가 있는 데이터의 집합 (데이터 중복 허용) - 배열과 비슷
- Queue : 빨대🥤처럼 한쪽에서 데이터를 넣고 반대쪽에서 데이터를 뺄 수 있는 집합
- First In First Out : 먼저 들어간 순서대로 값을 조회할 수 있다.
- Set : 순서가 없는 데이터의 집합 (데이터 중복 허용 안 함) - 순서 없고 중복 없는 배열
- Map : 순서가 없는 (Key, Value) 쌍으로 이루어진 데이터의 집합 (Key값 중복 허용 안 함)
- Java에서 컬렉션🧬 은 배열보다 다수의 참조형 데이터를 더 쉽고 효과적으로 처리할 수 있는 기능을 많이 가지고 있다.
- Collection🧬 은 기본형 변수가 아닌 참조형 변수를 저장!
- int의 참조형 변수 = Integer
- long의 참조형 변수 = Long
- double의 참조형 변수 = Double
- String은 원래부터 참조형 변수
List⛓️
1. ArrayList
배열(Array)처럼 일렬로 데이터를 저장하고 조회하고 순번 값(index)로 값을 하나씩 조회할 수 있다.
- 배열(Array)처럼 크기가 정해져 있지 않고 필요할 때마다 크기가 점점 더 늘어난다.
- ❓ Array 와 ArrayList의 차이. 크기를 지정하지 않아도 되는?
- Array처럼 크기를 고정하여 생성하는 것을 정적 배열,
ArrayList처럼 크기가 가변적으로 늘어나는 것을 동적 배열
- Array은 메모리에 연속된 공간을 요청한 사이즈만큼 받아서 실제 값을 저장하는 기본형 변수로 저장하기 때문에
정적 배열이다. - ArrayList는 생성시점에 작은 연속된 공간을 요청해서 참조형 변수들을 담아놓고, 값이 추가될 때 더 큰 공간이 필요하면 더 큰 공간을 받아서 저장하기 때문에 동적 배열 이다.
- Array은 메모리에 연속된 공간을 요청한 사이즈만큼 받아서 실제 값을 저장하는 기본형 변수로 저장하기 때문에
- 기능
- 선언 : ArrayList<Integer> intList 형태로 선언
- 생성 : new ArrayList<Integer>(); 형태로 생성
- 초기화 : 사이즈를 지정하는 것이 없기 때문에 초기화가 필요 없다.
- 값 추가 : intList.add({추가할 값}) 형태로 값을 추가합니다.
- 값 수정 : intList.set({수정할 순번}, {수정할 값}) 형태로 값을 수정
- 값 삭제 : intList.remove({삭제할 순번}) 형태로 값을 삭제
- 전체 출력 : intList.toString() 형태로 전체 값을 대괄호[]로 묶어서 출력
- 전체 제거 : intList.clear() 형태로 전체 값을 삭제
// ArrayList
// (사용하기 위해선 import java.util.ArrayList; 를 추가해야한다.)
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> intList = new ArrayList<Integer>(); // 선언 및 생성
intList.add(1);
intList.add(2);
intList.add(3);
System.out.println(intList.get(0)); // 1 출력
System.out.println(intList.get(1)); // 2 출력
System.out.println(intList.get(2)); // 3 출력
System.out.println(intList.toString()); // [1,2,3] 출력
intList.set(1, 10); // 1번순번의 값을 10으로 수정.
System.out.println(intList.get(1)); // 10 출력
intList.remove(1); // 1번순번의 값을 삭제.
System.out.println(intList.toString()); // [1,3] 출력
intList.clear(); // 전체 값을 삭제.
System.out.println(intList.toString()); // [] 출력
}
}
2. LinkedList
메모리에 남는 공간을 요청해서 여기저기 나누어서 실제 값을 담아 놓고, 실제 값이 있는 주소값으로 목록을 구성하고 저장한다.
- 기본적인 기능은 ArrayList 와 동일하지만 LinkedList는 값을 나누어 담기 때문에 모든 값을 조회하는 속도가 느리다.
대신에, 값을 중간에 추가하거나 삭제할 때는 속도가 빠르다. - 중간에 값을 추가하는 기능이 있다. (속도 빠름)
- 기능
- 선언 : LinkedList<Integer> linkedList 형태로 선언
- 생성 : new LinkedList<Integer>(); 형태로 생성
- 초기화 : 사이즈를 지정하는 것이 없기 때문에 초기화가 필요 없다.
- 값 추가 : linkedList.add({추가할 값}) 형태로 값을 추가합니다.
- 값 중간에 추가 : linkedList.add({추가할 순번}, {추가할 값}) 형태로 값을 중간에 추가
- 값 수정 : linkedList.set({수정할 순번}, {수정할 값}) 형태로 값을 수정
- 값 삭제 : linkedList.remove({삭제할 순번}) 형태로 값을 삭제
- 전체 출력 : linkedList.toString() 형태로 전체 값을 대괄호[]로 묶어서 출력
- 전체 제거 : linkedList.clear() 형태로 전체 값을 삭제
// LinkedList
// (사용하기 위해선 import java.util.LinkedList; 를 추가해야 한다.)
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<>(); // 선언 및 생성
linkedList.add(1);
linkedList.add(2);
linkedList.add(3);
System.out.println(linkedList.get(0)); // 1 출력
System.out.println(linkedList.get(1)); // 2 출력
System.out.println(linkedList.get(2)); // 3 출력
System.out.println(linkedList.toString()); // [1,2,3] 출력 (속도 느림)
linkedList.add(2, 4); // 2번 순번에 4 값을 추가.
System.out.println(linkedList); // [1,2,4,3] 출력
linkedList.set(1, 10); // 1번순번의 값을 10으로 수정.
System.out.println(linkedList.get(1)); // 10 출력
linkedList.remove(1); // 1번순번의 값을 삭제합니다.
System.out.println(linkedList); // [1,4,3] 출력
linkedList.clear(); // 전체 값을 삭제합니다.
System.out.println(linkedList); // [] 출력
}
}
3. Stack
값을 수직으로 쌓아놓고 넣었다가 빼서 조회하는 형식으로 데이터를 관리한다.
이걸 “나중에 들어간 것이 가장 먼저 나온다(Last-In-First-out)” 성질을 가졌다고 표현하며, 주로 상자와 비유해서 설명한다.
- 상자에 물건을 넣고 빼는 것처럼 밑에서 위로 쌓고, 꺼낼 때는 위에서부터 꺼내는 형식
- 그렇기 때문에 넣는 기능(push()) 과 조회(peek()), 꺼내는(pop()) 기능만 존재한다.
- 이렇게 불편하게 쓰는 이유는 최근 저장된 데이터를 나열하고 싶거나 데이터의 중복 처리를 막고 싶을 때 사용.
- 기능
- 선언 : Stack<Integer> intStack 형태로 선언
- 생성 : new Stack<Integer>(); 형태로 생성
- 추가 : intStack.push({추가할 값}) 형태로 값을 추가
- 조회 : intStack.peek() 형태로 맨 위값을 조회ㅡ
- 꺼내기 : intStack.pop() 형태로 맨 위값을 꺼낸다. (꺼내고 나면 삭제됨)
// Stack
// (사용하기 위해선 import java.util.Stack; 를 추가)
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Stack<Integer> intStack = new Stack<Integer>(); // 선언 및 생성
intStack.push(1);
intStack.push(2);
intStack.push(3);
while (!intStack.isEmpty()) { // 다 지워질때까지 출력
System.out.println(intStack.pop()); // 3,2,1 출력
}
// 다시 추가
intStack.push(1);
intStack.push(2);
intStack.push(3);
// peek()
System.out.println(intStack.peek()); // 3 출력
System.out.println(intStack.size()); // 3 출력 (peek() 할때 삭제 안 됐음)
// pop()
System.out.println(intStack.pop()); // 3 출력
System.out.println(intStack.size()); // 2 출력 (pop() 할때 삭제 됐음)
System.out.println(intStack.pop()); // 2 출력
System.out.println(intStack.size()); // 1 출력 (pop() 할때 삭제 됐음)
while (!intStack.isEmpty()) { // 다 지워질때까지 출력
System.out.println(intStack.pop()); // 1 출력 (마지막 남은거 하나)
}
}
}
Queue 🥤
빨대🥤처럼 한쪽에서 데이터를 넣고 반대쪽에서 데이터를 뺄 수 있는 집합
- First In First Out : 먼저 들어간 순서대로 값을 조회할 수 있다.
- 그렇기 때문에 넣는 기능(add()), 조회(peek()), 꺼내는(poll()) 기능만 존재한다.
- Queue는 생성자가 없는 껍데기라서 바로 생성할 수는 없다. (껍데기 = 인터페이스)
- 생성자가 존재하는 클래스인 LinkedList를 사용하여 Queue를 생성해서 받을 수 있다.
// LinkedList 를 생성하면 Queue 기능을 할 수 있습니다. (Queue 가 부모/ LinkedList 가 자식이기 떄문)
Queue<Integer> intQueue = new LinkedList<Integer>();
- 기능
- 선언 : Queue<Integer> intQueue 형태로 선언.
- 생성 : new LinkedList<Integer>(); 형태로 생성.
- 추가 : intQueue.add({추가할 값}) 형태로 값을 맨 위에 추가.
- 조회 : intQueue.peek() 형태로 맨 아래 값을 조회.
- 꺼내기 : intQueue.poll() 형태로 맨 아래 값을 꺼낸다. (꺼내고 나면 삭제됨)
// Queue
// (사용하기 위해선 java.util.LinkedList; 와 import java.util.Queue; 를 추가해야 한다.)
import java.util.LinkedList;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue<Integer> intQueue = new LinkedList<>(); // 선언 및 생성
intQueue.add(1);
intQueue.add(2);
intQueue.add(3);
while (!intQueue.isEmpty()) { // 다 지워질때까지 출력
System.out.println(intQueue.poll()); // 1,2,3 출력
}
// 다시 추가
intQueue.add(1);
intQueue.add(2);
intQueue.add(3);
// peek()
System.out.println(intQueue.peek()); // 1 출력 (맨먼저 들어간값이 1 이라서)
System.out.println(intQueue.size()); // 3 출력 (peek() 할때 삭제 안됐음)
// poll()
System.out.println(intQueue.poll()); // 1 출력
System.out.println(intQueue.size()); // 2 출력 (poll() 할때 삭제 됐음)
System.out.println(intQueue.poll()); // 2 출력
System.out.println(intQueue.size()); // 1 출력 (poll() 할때 삭제 됐음)
while (!intQueue.isEmpty()) { // 다 지워질때까지 출력
System.out.println(intQueue.poll()); // 3 출력 (마지막 남은거 하나)
}
}
}
Set 📚
순서가 없는 데이터의 집합 (데이터 중복 허용 안 함) - 순서 없고 중복 없는 배열
- 순서가 보장되지 않는 대신 중복을 허용하지 않도록 유지할 수 있다.
- Set은 그냥 Set으로 쓸 수도 있지만 HashSet, TreeSet 등으로 응용하여 사용할 수 있다.
- Set는 생성자가 없는 껍데기라서 바로 생성할 수는 없다. (껍데기 = 인터페이스)
- 생성자가 존재하는 클래스인 HashSet를 사용하여 Set를 생성해서 받을 수 있다.
- 기능
- 선언 : Set<Integer> intSet 형태로 선언
- 생성 : new HashSet<Integer>(); 형태로 생성
- 추가 : intSet.add({추가할 값}) 형태로 값을 맨 위에 추가
- 삭제 : intSet.remove({삭제할 값}) 형태로 삭제할 값을 직접 지정
- 포함 확인 : intSet.contains({포함 확인 할 값}) 형태로 해당 값이 포함되어있는지 boolean 값으로 응답
🔎 HashSet 외에도 TreeSet, LinkedHashSet 이 있다.
- HashSet : 가장 빠르며 순서를 전혀 예측할 수 없음
- TreeSet : 정렬된 순서대로 보관하며 정렬 방법을 지정할 수 있음
- LinkedHashSet : 추가된 순서, 또는 가장 최근에 접근한 순서대로 접근 가능
즉, 보통 HashSet 을 쓰는데 순서 보장이 필요하면 LinkedHashSet 을 주로 사용한다.
// Set
// (사용하기 위해선 import java.util.Set; 와 java.util.HashSet; 를 추가해야 한다.)
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Set<Integer> intSet = new HashSet<Integer>(); // 선언 및 생성
intSet.add(1);
intSet.add(2);
intSet.add(3);
intSet.add(3); // 중복된 값은 덮어쓰기.
intSet.add(3); // 중복된 값은 덮어쓰기.
for (Integer value : intSet) {
System.out.println(value); // 1,2,3 출력
}
// contains()
System.out.println(intSet.contains(2)); // true 출력
System.out.println(intSet.contains(4)); // false 출력
// remove()
intSet.remove(3); // 3 삭제
for (Integer value : intSet) {
System.out.println(value); // 1,2 출력
}
}
}
Map 🗝🚪
key-value 구조로 구성된 데이터를 저장.
- key-value 형태로 데이터를 저장하기 때문에 기존에 순번으로만 조회하던 방식에서, key 값을 기준으로 vlaue를 조회할 수 있다.
- key 값 단위로 중복을 허용하지 않는 기능을 가지고 있다.
- Map 은 그냥 Map으로 쓸 수도 있지만 HashMap, TreeMap등으로 응용하여 사용할 수 있다.
- Map으로 쓸 수도 있지만 HashSet, TreeSet 등으로 응용하여 사용할 수 있다.
- 기능
- 선언 : Map<String, Integer> intMap 형태로 Key타입과 Value타입을 지정해서 선언
- 생성 : new HashMap<>(); 형태로 생성
- 추가 : intMap.put({추가할 Key값},{추가할 Value값}) 형태로 Key에 Value값을 추가
- 조회 : intMap.get({조회할 Key값}) 형태로 Key에 있는 Value값을 조회
- 전체 key 조회 : intMap.keySet() 형태로 전체 key 값들을 조회
- 전체 value 조회 : intMap.values() 형태로 전체 value 값들을 조회
- 삭제 : intMap.remove({삭제할 Key값}) 형태로 Key에 있는 Value값을 삭제
🔎 HashMap 외에도 TreeMap 이 있다.
- HashMap : 중복을 허용하지 않고 순서를 보장하지 않음, 키와 값으로 null이 허용
- TreeMap : key 값을 기준으로 정렬을 할 수 있습니다. 다만, 저장 시 정렬(오름차순)을 하기 때문에 저장시간이 다소 오래 걸림
// Map
// (사용하기 위해선 import java.util.Map; 를 추가.)
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> intMap = new HashMap<>(); // 선언 및 생성
// 키 , 값
intMap.put("일", 11);
intMap.put("이", 12);
intMap.put("삼", 13);
intMap.put("삼", 14); // 중복 Key값은 덮어쓰기.
intMap.put("삼", 15); // 중복 Key값은 덮어쓰기.
// key 값 전체 출력
for (String key : intMap.keySet()) {
System.out.println(key); // 일,이,삼 출력
}
// value 값 전체 출력
for (Integer key : intMap.values()) {
System.out.println(key); // 11,12,15 출력
}
// get()
System.out.println(intMap.get("삼")); // 15 출력
}
}
🔎 length vs length() vs size() - 길이값 가져오기
1. length
- arrays(int[], double[], String[])
- length는 배열의 길이를 조회
2. length()
- String related Object(String, StringBuilder etc)
- length()는 문자열의 길이를 조회(ex. “ABCD”.length() == 4)
3. size()
- Collection Object(ArrayList, Set etc)
- size()는 컬렉션 타입 목록의 길이를 조회
*자바 강의의 완벽한 숙지를 위해 강의 자료를 정리한 내용
TIL 10월 20일
'TIL (ToDay I LearNEd) > Java' 카테고리의 다른 글
자바의 정석 CH 5 배열 (0) | 2024.11.20 |
---|---|
Java의 기본 개념 (1) | 2024.10.14 |
Java_String format 형식 (0) | 2024.10.10 |
본격적으로 Java를 시작하기 전에 알아야 할 것들. JVM, 변수 (0) | 2024.10.08 |
Java의 작동 원리와 장점 (0) | 2024.09.09 |