TIL (ToDay I LearNEd)/Java

Java 문맥 구성과 데이터 관리 (연산자, 조건문, 반복문, 배열, 컬렉션)

sooyeoneo 2024. 10. 20. 05:13

계산 하기_연산자 ➕➖✖️➗

계산할 대 계산의 대상이 되는 것이 피연산자이며, 계산의 목적이 되는 것이 연산자이다.

  • 연산자 : 덧셈, 뺄셈처럼 계산할 기호 ➕
  • 피연산자 : 연산자로 인해 계산되는 숫자 🔢

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() 메서드 

배열이 지원하는 메서드로써 해당 배열이 길이 값을 응답해준다. 

배열의 길이는 처음에 선언한 크기를 가진다.

 

초기화 (🗳️ = { ... } )

배열(분류통)을 초기화

  1. 중괄호 { } 를 사용해서 초기화
  2. 반복문 for문을 사용해서 초기화 (또는 향상된 for문)
  3. 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차원 배열🗳️🗳️

1차원 배열과 2차원 배열을 이해하기 쉽도록 그림으로 표현

 

저장소 관점으로 그림을 그려서 표현

 

선언 

2차원 배열을 선언할 때 1차원 배열에 대괄호를 하나 더 추가.

 

  • int[ ] [ ]  array
  • int array [ ] [ ]
  • int[ ] array[ ]

1차원 배열과 2차원 배열의 선언에 따른 저장소 할당의 차이점

 

 

생성 

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차원 배열 이상의 다차원 배열 이해

  1. 2차원 배열 외에도 3차원, 4차원 등..이 있지만 거의 대부분 3차원까지만 사용하는 경우가 많다.
  2. 3차원 배열?
    • 3차원 배열 선언은 2차원 배열 생성에 괄호를 하나 더해주면 된다.
      • ex. int[ ][ ][ ] multiArrary
    • 초기화할 때는 중괄호를 더 추가하면 된다.
    • {{{배열원소1}, {배열원소2}}, {{배열원소3}}} 와 같은 형태로 초기화가 가능
// 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값 중복 허용 안 함)

 

 

  • Collection🧬 은 기본형 변수가 아닌 참조형 변수를 저장!
    • int의 참조형 변수 = Integer
    • long의 참조형 변수 = Long
    • double의 참조형 변수 = Double
    • String은 원래부터 참조형 변수

 

List⛓️

1. ArrayList

배열(Array)처럼 일렬로 데이터를 저장하고 조회하고 순번 값(index)로 값을 하나씩 조회할 수 있다.

- 배열(Array)처럼 크기가 정해져 있지 않고 필요할 때마다 크기가 점점 더 늘어난다.

  •  Array 와 ArrayList의 차이. 크기를 지정하지 않아도 되는?
  • Array처럼 크기를 고정하여 생성하는 것을 정적 배열,
    ArrayList처럼 크기가 가변적으로 늘어나는 것을 동적 배열 
    • Array은 메모리에 연속된 공간을 요청한 사이즈만큼 받아서 실제 값을 저장하는 기본형 변수로 저장하기 때문에
      정적 배열이다.
    • ArrayList는 생성시점에 작은 연속된 공간을 요청해서 참조형 변수들을 담아놓고, 값이 추가될 때 더 큰 공간이 필요하면 더 큰 공간을 받아서 저장하기 때문에 동적 배열 이다.
    따라서, 기본형 변수로 저장하는 Array는 정적 배열이고, 참조형 변수로 저장하는 ArrayList는 동적 배열!
  • 기능
    • 선언 : 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일