Java - 정리 전

박상원·2024년 2월 13일

메모

목록 보기
7/8

System.out.println() : 괄호안의 내용을 출력하고 줄바꿈을 한다
System.out.print(): 내용을 출력하고 줄바꿈을 하지 않는다

new는 객체를 생성하는 연산자이다

final static double PI = 3.141592;
위와 같은 상수 변수같은 경우는 메인메소드 바깥쪽(class Main이 아닌 static void main바깥)에서 선언한다
final은 한 번 선언이 되면 바뀔 수 없다(즉 상수)는 의미이다
static은 하나의 class에서 공유하는 자원이라는 뜻이다

int a = 200;
System.out.println("10진수 : " + a);
System.out.format("8진수 : %o", a); <- %o는 10진수를 8진수로 바꾸는 기능
System.out.format("16진수 :%x ", a); <- %x는 10진수를 16진수로 바꾸는 기능

클래스 이름에는 메소드나 함수이름이 들어갈 수 없다.
import java.util.*
ex) public class Scanner { ~~~} <Scanner 는 이미 있는 클래스 이름이므로 안됨

■■■■■■■■■■■■■■■■■■기타■■■■■■■■■■■■■■■■■■
cmd로 자바파일 실행할때
cd C:\Users\nnayu\Desktop\new(자바파일경로) 로 자바파일이 있는 경로로 진입
javac Hello.java(자바파일) 로 자바파일 컴파일 실행해서 클래스 파일 생성
java Hello(클래스파일) 로 실행

javac로 컴파일 할 때 인코딩에러 나올시 -> javac File.java -encoding utf-8
이런식으로 -encoding utf-8(인코딩 종류) 를 마지막에 붙여서 컴파일 시 인코딩을 지정해 준다.

만약 기본 클래스를 찾거나 로드할 수 없다고 나오면 아래 링크참고
https://blog.naver.com/PostView.nhn?blogId=hotkimchi13&logNo=221184700791

환경변수 -> 시스템변수 -> CLASSPATH 편집 -> 변수값이 %JAVA_HOME%\lib 로 되어있다면
%JAVA_HOME%\lib;. <-으로 수정

다른 클래스의 윈도우를 띄울 때, ex) 로그인창 클래스에서 메인화면 클래스창을 띄우고 싶을 때 new MainWindow(); 와 같이 사용하는데,
이때, MainWindow의 main함수에는 new MainWindow(); 와 같이 화면을 띄우는 코드만 있어야함

■■■■■■■■■■■■■■■■■■입력■■■■■■■■■■■■■■■■■■
참고 ↓
https://st-lab.tistory.com/41
https://limkydev.tistory.com/170

**InputStreamReader (패키지 java.io.*)***
ex)
InputStreamReader rd = new InputStreamReader(System.in); //System.in은 사용자가 입력한 값들
System.out.println("숫자 입력");
int a = rd.read();

System 클래스의 in 변수는 '표준입력스트림' 이며 일반적으로 키보드나 터미널에서 입력을 통해 넣어주는
값들은 모두 System.in을 통해 연결된다.
정리하자면 in 이라는 변수는 InputStream의 변수로 결국 InputStream 타입의 새 변수를 선언하고 그 변수에
System.in 을 할당시킬 수도 있다는 뜻이다.

InputStreamReader를 사용할땐 반드시 예외처리를 해주어야 한다.
try-catch 문으로 예외를 처리해주어도 되고 위 처럼 메소드에 throws IOException 으로 처리해줘도 된다.
Scanner 나 System.out.print 메소드의 경우 해당 메소드 안에서 자체적으로 예외처리를 하기 때문에
예외처리를 해줄 필요가 없었지만 기본적으로 io 패키지는 IOException 이라는 예외를 던지기 때문에
이를 처리해주어야 정상적으로 컴파일된다.

메인함수에 throws로 예외처리 하는법 ↓
public static void main(String[] args) throws IOException {

ex)
InputStream inputstream = System.in;
int a = inputstream.read();
System.out.println(a);
9입력 >> 57
923입력 >> 57
위와 같이 다른 값을 넣어도 57이 나오는 이유는 InputStream.read() 의 두가지 특성 때문
1. 입력받은 데이터는 int 형으로 저장되는데 이는 해당 문자의 시스템 또는 운영체제의 인코딩 형식의(필자의 경우 UTF-8) 10진수로 변수에 저장된다.
2. 1byte 만 읽는다.

만약 입력받은 문자가 2byte 이상으로 구성되어있는 인코딩을 사용할 경우 1byte 값만 읽어들이고 나머지는 읽지 않고 스트림에만 남아있기 때문에
출력할 때는 해당 데이터의 1Byte 에 대한 인코딩 값을 10진수로 변환한 값이 출력되는 것이다.
예를 들어 10000001 00001111 의 값을 갖고있는 2Byte 문자 하나를 입력했다면
1Byte 로 각각 나뉘어 스트림을 통해 10000001 과 00001111 의 값을 가지는, 1Byte 데이터가 2개가 있다는 의미다.
하지만 프로그램에서 read() 를 한 번만 쓰면 먼저 입력된 10000001 을 읽지만, 00001111 은 스트림에 계속 남아있게 된다.
만약에 나머지 1Byte 도 읽고싶다면 read() 메소드를 두 번 써야된다. 이러한 바이트 단위로 주고받는 스트림을 바이트 스트림이라고도 한다.

****Scanner***
import java.util.scanner; //입력 받는 기능인 scanner를 사용하기 위해선 import해줘야한다. import는 메인클래스(public class)(main메소드아님) 바깥에 해줘야한다.

입력받는 타입에 따라
nextInt() : 정수형
next() : 문자열

Scanner sc = new Scanner(System.in); //Scanner클래스의 sc라는 인스턴스(변수) 생성후 초기화. System.in은 콘솔창 같은 곳에서 입력을 받는다는 의미
System.out.print("정수입력");
int i = sc.nextInt(); //int(정수)를 입력받아 i에 저장한다.
System.out.println("입력된 정수는 "+i+"입니다.");
sc.close();

■■■■■■■■■■■■■■■■■■연산자■■■■■■■■■■■■■■■■■■
**삼항 연산자*
int a = 10, b = 20;
int c = (a > b) ? 1 : 0
괄호안이 조건식이고 물음표 뒤가 출력이다
괄호안의 조건이 참이면 1을, 거짓이면 0을 출력한다
(물론 출력값 변경가능)

■■■■■■■■■■■■■■■■■■클래스■■■■■■■■■■■■■■■■■■
클래스 = 변수(필드) + 메소드(함수)
클래스는 대문자로 시작하며 파일명과 일치해야함 여러 사용자가 사용하기 위해선 public을 붙인다.
클래스 로부터 객체를 생성할 땐 new명령어를 사용한다. 클래스명 객체명 = new 클래스명();
이렇게 생성된 객체는 클래스가 가지고있는 속성과 함수를 사용할 수 있게된다.

속성(필드) - 속성은 클래스가 가지고 있는 변수이다
속성은 변수와 똑같이 선언한다 //자료형 속성명 = 값;
속성변경 -> //객체명.속성명 = 값;
만약 변경을 할 수 없게 만들고 싶으면 선언할 때 final을 붙인다 //final String color = "black"

****클래스 상속**
상속해주는 클래스를 슈퍼클래스, 상속 받는 클래스를 서브 클래스라 한다.
상속을 하면 슈퍼클래스에서 private 형의 변수나 메소드를 제외한 모든 메소드와 멤버변수가 서브클래스에 상속된다.(생성자 함수 포함)
상속받을 때 생성자 또한 상속 되는데, 서브클래스의 생성자를 실행하기 전에 슈퍼클래스의 생성자를 먼저 실행한다.

ex)
class A{ A(){ System.out.print("A"); }
class B extends A{ B(){System.out.print("B"); }
class C extends B{ C(){System.out.print("C"}; }
여기서, C test = new C(); 를 하면 결과>>> A B C
C의 생성자를 실행 하기전, C가 B에게 상속을 받았다는것을 확인하고 B로 간후, B또한 A에게 상속받았다는 것을 확인한후
A로 가서 A의 생성자를 실행해서 A가 출력된다.
그후 B의 생성자를 실행해 B가 실행되고, 이후 C의 생성자가 실행되어 C가 출력된다.

이렇게 슈퍼클래스의 생성자를 먼저 실행하는 이유는 만약 서브클래스안에 슈퍼클래스의 멤버 변수가 있다면, 이는 초기화 되지 않았을 것이다.
그런데 초기화 되지않은 슈퍼클래스의 멤버변수가 서브클래스에 상속되면 서브클래스에선 슈퍼클래스의 멤버변수를 사용할 수 없다(초기화가 안됐으니)
따라서 슈퍼클래스의 생성자 먼저 실행하고 이후 서브클래스의 생성자를 실행한다.

ex)
class A{ int a; }
class B extends A{ int b = a+10; }
class C extends B{ int c = a + b; }
슈퍼클래스의 생성자 먼저 실행되지 않는다고 가정하면,
여기서 C클래스의 객체를 생성하면 C클래스 내에 a와 b는 초기화가 되어있지 않으므로 쓸 수가 없다.
따라서 A클래스의 생성자를 먼저 실행하여 a를 초기화 한 후, B클래스의 생성자를 실행하여 b를 초기화한다.
이후 C클래스의 생성자를 실행하여 c를 초기화 할 수 있게된다.

서브클래스에서 슈퍼클래스의 생성자를 쓰려면 super()를 사용해야 한다.
class A { A(int a){ 임의코드... } }
class B extends A { B(int aa){ super(aa); } }
이렇게 super()의 괄호안에 값을 넣으면 생성자를 실행할 때 매개변수를 넣을 수 있다.
주의할 점은 서브클래스에서 super()를 사용할 때, 서브클래스의 생성자 안에서 사용해야 하며, 그 생성자의 최상단에 super()가 위치해야 한다.
또한 슈퍼클래스의 생성자에 매개변수가 필요한데 서브클래스에서 명시적으로 super()를 쓸때 매개변수를 넣지 않으면 에러가 난다.
가령 위 코드에서 B(int aa){ super(); } 이렇게 쓰거나, B(int aa){ 임의코드.. } 이런식으로 아예 슈퍼클래스의 생성자 자체를 실행하지 않을 경우, 에러가 난다
서브클래스의 객체가 생성되기 전엔 슈퍼클래스의 객체를 먼저 생성한다. 따라서 B의 객체를 생성하기전 A의 객체를 생성하게 되는데, A클래스의 생성자는 실행하려면 매개변수가 필요하다.
그런데 서브클래스에서 이것을 명시해주지 않으면 매개변수를 넣을 수가 없어 에러가 난다.
매개변수를 넣지 않으면 디폴트 생성자가 생성되지 않을까 하고 생각할 수 있으나, 디폴트 생성자는 클래스내에 생성자가 아예 없을때만 생성된다.

■■■■■■■■■■■■■■■■■■함수(메소드)■■■■■■■■■■■■■■■■■■
클래스 안에 있는 함수를 뜻하며
메소드는 반드시 클래스안에 선언되어야 한다.
사용할 때도 클래스명.함수() 또는 객체선언 후 객체명.함수() 로 사용

기본적으로 어떤 클래스의 메소드를 쓸때는 "해당클래스로 선언된 변수이름"."메소드이름"(입력값) 을 사용한다.
단, 정적 메소드나 정적필드(변수)의 경우 선언은 static int a = 0; 메소드는 static int fuction() { return a; }와 같이 static을 붙여 선언하고
정적필드, 메소드를 불러올땐 class.a 메소드는 class.fuction() 와 같이 "해당 정적필드, 메소드의 클래스명"."정적필드, 메소드 이름"(메소드일 경우 이 입력값 괄호까지) 이렇게 출력한다

static int max(int a, int b){
int c = (a > b) ? a : b;
return c;
}
함수를 선언할땐 반환값의 자료형, 함수이름, 매개변수(괄호안의 입력값)와 함수내용(중괄호 안의 내용)
및 리턴값(반환값)으로 이루어진다
함수는 main메소드 바깥에서 선언되어야 한다
따라서 static은 main메소드 안에서 사용하기 위해 붙인다.

main메소드가 static으로 선언 되었다면 해당 클래스 내의 다른 함수들도 모두 static으로 선언되어야 한다.
또한 static으로 선언된 함수는 해당 클래스내에서 사용할때 클래스 안붙이고 사용가능
ex)
클래스가 Project1 일 경우, 클래스 내에서 static int printValue(int a){........}
으로 선언된 함수가 있다고 하면 Project1 클래스 내에서는 Project1.printValue(30); 와 같이 안쓰고
printValue(30); 이렇게 바로 쓸 수 있다. 그러나 다른 클래스에서 이 함수를 쓰려면 Project1.printValue(30); 이렇게 써야한다.

필드도 마찬가지로 static으로 선언되었다면 객체이름.필드 <-이런식으로 쓸 필요없이 바로 쓰면 된다.

**this*
주로 함수정의에서 많이 사용.
ex)
public String name = "가나다"
public void setName(String name){
this.name = name; //여기서 this가 붙은 name변수는 멤버변수name을 뜻하고, 오른쪽 name은
} setName함수가 매개변수로 받은 name변수를 뜻한다.

*pow함수와 자료형 변환****
double a = Math.pow(3.0, 20.0);
System.out.println("3의 20제곱은 " + (int) a + "입니다.");
Math.pow(3.0, 20.0)부분은 Math라는 클래스의 pow라는 함수를 사용한다는 뜻이며,
입력값 3.0과 20.0은 3의 20제곱을 의미한다.
(int) a는 double형 이었던 a의 자료형을 int형으로 변환한다는 뜻이다.

***public, static, void*
(명품 java programming 146P 참고)
public - 객체에서만 접근할 수 있는 함수에 붙인다. public이 붙은 메소드를 사용하기 위해선 객체를 생성하고 객체명을 통해서만 호출이 가능
ex) public void showname(){ System.out.println("내 이름은" + name + "입니다"); }
Student st1 = new Student();
st1.showname(); //객체명.showname() 으로 호출가능

static - static은 이 함수가 객체에 속한게 아니라 클래스에 속한것을 알려준다. 따라서 static(정적)함수는 객체 생성 없이
클래스명.함수() 로 사용이 가능하다. 같은 클래스 안에서는 함수명 만으로도 호출이 가능하다
static을 사용하면 같은 기능을 하는 함수라도 함수이름을 매번 다르게 정해주어야 한다
(예를들어 버튼을 클릭하면 이름을 출력하는 onclick() 이라는 함수가 있다면 버튼이 여러개일경우 onclick1(), onclick2() ...등으로 이름들 다르게 해야한다.
하지만 객체를 생성하고 객체내에서 버튼을 호출하면 onclick() 하나로 할 수 있다.

void - void는 리턴값이 없다는 것을 의미한다 리턴값을 반환해야 한다면 int, String, double등 자료형을 써줘야한다.

public과 static은 위의 특성때문에 같이 사용할 수 없다. 그러나 main함수만이 유일하게 이 둘을 같이 쓸 수 있다.

**생성자 함수*
함수는 리턴값을 표시하는 void, int, String 등을 가져야 하지만 생성자 함수는 이러한 것이 필요없고 앞에 public만 붙이면 된다
생성자 함수는 객체 생성시 가져야 할 속성과 함수들을 미리 정해놓기 때문이다.

****메소드 오버로딩***
메소드 오버로딩은 똑같은 이름의 메소드를 두 개 이상 만드는 것이다.
ex)
class Abc{
void print(){System.out.print("1"};}
void print(int a){System.out.print("2");}
}
만약 print메소드를 실행할때 매개변수를 없이 실행하면 첫번째 print가 실행되고,
int형 매개변수를 넣으면 두번째 print가 실행된다.

메소드 오버로딩의 조건은 메소드의 이름이 같을 때, 매개변수의 개수 또는 타입이 달라야 한다. 또한 메소드의 자료형(리턴값 자료형)은 일치해야 한다.
반환타입(void, int 등)이 다른 것은 해당하지 않는다. 매개변수의 개수와 타입이 같은데 하나는 void이고 하난 리턴값이 int일때
이것은 오버로딩이 성립되지 않고 에러가 난다.

ex)
void print(){ }
int print(){ }
위 두개는 매개변수의 개수와 타입이 같으므로 다른 메소드로 취급되지않고 에러가 난다.

void print(){ }
void print(int a){ }
위 두개는 매개변수의 수가 다르므로 오버로딩이 성립한다.

void print(int a){ }
void print(String a){ }
위 두개도 매개변수의 타입이 다르므로 오버로딩이 성립한다.

***메소드 오버라이딩*
클래스 상속에서, 수퍼클래스에서 정의한 메소드를 서브클래스에서 다시 정의하는 것을 의미한다.
이때, 슈퍼클래스의 메소드와 서브클래스의 메소드의 매개변수의 개수와 타입이 같고, 이름도 같아야 하며, 시그니처, 반환 자료형 또한 같아야 오버라이딩이 성립된다.
class A{ void print(){} }
class B extends A{ void print(){System.out.print("오버라이딩");} }
클래스 B가 A에게 상속을 받으면 A의 print메소드는 B에 상속돼야 하지만 이미 B에 동일한 이름의 print메소드가 있다.
또한 B의 print는 A의 print와 매개변수의 개수와 타입(void, int등)이 같다.
이럴때를 오버라이딩 이라고 하며, A의 print는 B에게 상속되지 않고, B의 print만 남아있는다.
이렇듯 슈퍼 클래스의 메소드를 그대로 이어받지 않고 수정하여 사용하고 싶을 때 이용하는 것이 메소드 오버라이딩이다.

그런데 만약
class A{ void print(){} }
class B extends A{ void print(int a){System.out.print("오버라이딩");} }
클래스B를 이렇게 만든다면, 매개변수의 개수와 타입이 다르므로 이것은 오버라이딩이 되지않고 오버로딩이 된다.

또한 시그니처 또한 같아야 하는데 시그니처란 public, protected, static, int 등 메소드 앞에 붙는 접근 수정자와 자료형등을 통틀어 말한다.
이때 자료형은 같아야 한다.
class A{ public void print(){} }
class B extends A{ protected void print(){System.out.print("오버라이딩");} }
그런데 접근 수정자의 경우는 범위가 같거나 넓어 지는것은 상관 없으나 범위가 좁아지면 오류가 발생한다.
위와 같이 B가 A에게 상속을 받았는데, B의 print메소드의 범위는 protected고 A는 public이다.
B메소드의 접근 수정자가 A에 비해 범위가 좁아진 것이다. 이러면 오버라이딩이 성립되지 않고 에러가 발생한다.

class A{ protected void print(){} }
class B extends A{ public void print(){System.out.print("오버라이딩");} }
그러나 이렇게 protected -> public으로 범위가 같거나 넓어지는 것은 상관없다.

또한 반환 자료형 또한 같아야 함.
만약 A의 print가 void타입인데 A에게 상속 받은 B의 print가 int라면 에러남

■■■■■■■■■■■■■■■■■■인터페이스■■■■■■■■■■■■■■■■■■
한개의 클래스가 여러개의 클래스에 상속을 해주는것은 가능하다.
그런데 한개의 클래스가 여러개의 클래스에게 상속을 받는건 불가능하다.
즉 다중 상속은 불가능하다.
다만 인터페이스를 사용하면 가능하다.

인터페이스는 다중 상속을 위한 것으로, 상수 + public 형의 추상 메소드로 이루어진다.
인터페이스는 클래스와 달리 멤버변수, 생성자, 일반메소드를 가질 수 없다.
또한 추상메소드를 가지니 객체를 생성할 수 없다.

상수 : public static final 형의 상수로서, public static final은 생략 가능
static은 객체를 생성할 수 없으니, 모든 상수가 인터페이스 소속의 상수이므로 붙인다.
public은 인터페이스는 상속을 해주는 형태로만 사용할 수 있으니 사용범위에 제한을 두지 않으므로 붙인다.
추상메소드 : abstract public 형의 메소드로서 abstract public은 생략 가능
상수와 마찬가지로 public은 사용범위에 제한을 두지 않으므로 붙이고,
abstract는 인터페이스가 추상메소드 밖에 가질 수 없으니 붙인다.

인터페이스 정의 형태
[public] interface 인터페이스이름(첫글자 꼭 대문자는 아니여도 됨) [extends 인터페이스1, 인터페이스2...] {
.... //상수 선언
.... //public형의 추상메소드
}
//인터페이스는 다른 여러개의 인터페이스로부터 상속을 받을 수도있고, 클래스에게 상속 받을 수도 있다.
ex) extends 인터페이스1, 클래스1, 인터페이스2 <- 이렇게 클래스와 인터페이스 둘 다에게 상속받을 수도 있다.

ex)
public interface Student extends Man, Study { //Man과 Study인터페이스 에게 상속 받음
int study_time = 8;
public void study();
}

ex)
interface Example {
int max = 100; //public static final int max와 같은 의미 이지만 public static final는 생략 가능 하므로 이렇게 쓴다.
double pi 3.14; //public static final double pi 와 같은 의미지만 public static final은 생략 가능하므로 이렇게 쓴다.
void show(); //abstract public void show()와 같은 의지만 abstract public은 생략 가능하므로 이렇게 쓴다.
}

인터페이스가 인터페이스에게 상속 받을땐 extends를 쓰지만, 클래스가 인터페이스에게 상속 받을땐 implements를 쓴다.
인터페이스가 인터페이스에게 상속받을 때 : extends
클래스가 클래스에게 상속받을 때 : extends
클래스가 인터페이스에게 상속받을 때 : implements
그런데 인터페이스가 클래스에게 상속 받는건 불가능하다. 왜냐면 클래스에는 일반적인 메소드, 멤버변수 등이 들어갈 수 있는데,
인터페이스는 추상메소드와 상수만 정의할 수 있으므로 애초에 인터페이스가 클래스에게 상속받지 못하게끔 한것이다.
ex)
class B extends A implements C, D{ //A클래스와 C, D인터페이스에게 상속 받음
public void sum(){ ...... } //인터페이스에게 상속받은 추상메소드를 반드시 재정의 해야함. 안하면 추상클래스가 됨
} 이때, 인터페이스는 무조건 public형 이므로, 재정의 할때 public으로 선언해야 한다.
클래스에서는 public 안붙이면 자동으로 package형으로 선언되기 때문

■■■■■■■■■■■■■■■■■■변수■■■■■■■■■■■■■■■■■■
지역변수 : 메소드 안에서 선언된 변수로, 변수가 선언된 해당 메소드 내부에서만 사용가능

전역변수, 필드, 멤버변수 : 클래스 영역에서 정의한 변수로, 모든 메소드에서 사용가능한것
(메인클래스(static void main이 아닌 public class)내에서 선언한다)

정적필드 와 정적메소드 : 해당 클래스의 필드나 메소드를 인스턴스(객체)를 생성하지 않고 쓸 수 있다
변수나 메소드를 선언할 때 앞에 static을 붙이면 정적필드, 메소드가 된다.

■■■■■■■■■■■■■■■■■■자료형■■■■■■■■■■■■■■■■■■
**기본 자료형*
정수 자료형
byte - 1byte
short - 2byte
int - 4byte
long - 8byte

실수자료형
float - 4byte //float은 변수뒤에 꼭f를 붙여야 한다 안그럼 데이터 타입이 맞지않아 오류가 난다.
double - 8byte

문자형
char - 2byte

참,거짓 값
boolean - 1byte

**Stirng**
String은 클래스의 한 종류이며, 문자열 자료형이라고도 할 수 있다.
String name = "psw"; <- String은 문자열을 저장할 수 있으며 내장함수를 가지고있다
System.out.println(name.substring(0,1)); <- String의 내장함수중 하나인 substring이다 0,1은 0번째 글자부터 1번째 전까지의 글자만 출력한다는 뜻

p

String a = "I Love You"
if(a.contains("Love")) //contains는 String클래스에 내장된 내장함수로, String문자열 내에 괄호안의 값이 있으면 중괄호 내의 코드를 실행한다.
{ System.out.println("Me Too"); }

**형변환***
형변환 방법1 (새로운 변수를 기존과 다른 자료형으로 선언하여 그곳에 저장한다)
int i = 10
double a = i
long b = i
float f = 3.14i
a = f

형변환 방법2 (기존에 있던 변수를 자료형만 바꾼다.)
int a;
byte b;
b = (byte) a;

**참조형 자료형***
클래스형
인터페이스형
배열형

■■■■■■■■■■■■■■■■■■IF문■■■■■■■■■■■■■■■■■■
String a = "I Love You"
if (a.contains("Love")){
System.out.println("Me Too");
} //if문의 조건식이 참일경우 실행한다
else if (a.contains("You")){
System.out.println("I Love You");
} //if문의 조건식이 거짓이고 else if의 조건식이 참일경우 실행한다.
else
{ System.out.println("I Hate You"); } //if문과 else if의 조건식이 모두 거짓일경우 실행한다

if (조건식) System.out.println("가나다");
// 이렇게 실행식이 하나라면 조건식 바로옆에 중괄호없이 쓸 수 있다.

if (조건식) {
실행식1;
실행식2;
}
// 실행식이 여러개면 이렇게 중괄호를 써야한다.

if (조건식) 실행식1
else if (조건식2) 실행식2
else if (조건식3) 실행식3
else 실행식4
//만약 조건식 2가 참이라면 실행식 2만 출력하고, 나머지 조건식3 이나 else문은 무시하고 if문을 빠져나간다.

■■■■■■■■■■■■■■■■■■switch-case문■■■■■■■■■■■■■■■■■■
switch (조건식) { //조건식은 결과가 정수형, 문자형, 문자열인 경우만 허용
case 상수식1 : 문장1
case 상수식2 : 문장2
.
.
.
case 상수식n : 문장n
default : 묵시적인 문장 //상수식이 모두 거짓이면 default의 묵시적인 문장을 실행

//만약 조건식 = 상수식2이면, 문장2 실행후, 상수식3.... 등의 조건은 무시하고 문장3, 문장4..... 묵시적인 문장까지 모두 실행한다.
이렇게 하고 싶지 않으면 break를 넣어줘야 한다.

ex)
int num = 1;
switch(num) {
case 0 : System.out.println("숫자는 0");
case 1 : System.out.println("숫자는 1");
case 2 : System.out.println("숫자는 2");
default : System.out.println("숫자는 0~2가 아님");
}
결과>>> 숫자는 1
숫자는 2
숫자는 0~2가 아님
//break를 안넣으면 이렇게 끝까지 모두 실행한다.

■■■■■■■■■■■■■■■■■■for문과 while문■■■■■■■■■■■■■■■■■■
C언어와 동일하다
for(;;)는 while(true)와 똑같이 무한 루프된다
break; 이용해 반복문이나 switch문을 빠져나올 수 있다.

for (i=1, sum=0; i<=10; i++) <- 초기화 부분에 두개 이상 초기화를 할 수도있다.

for (i=1, sum=0; i<=10;)
sum += i++; <- 증감식이 괄호안에 없어도 이렇게 실행식안에 넣어도 된다.

i=1; sum=0; <- 초기화를 괄호안에서 안해도 된다.
for ( ; i<=10;) <- 초기화 안해도 세미콜론은 있어야 한다.
sum+= i++;

i=1; sum=0;
for ( ; ; ) <-초기화, 증감식, 조건식 모두 괄호안에서 안해도 된다.
괄호밖이든 안이든 있기만 하면 사용가능
if (i<=10) sum += i++;

****do-while****
ex)
int i=15;
do {
printf("%d\n", i);
i++;
} while (i<10);
do while은 while의 조건을 만족하지 않아도 무조건 한번은 중괄호 안의 내용을 실행하고,
그뒤 while의 조건을 만족하면 반복, 만족하지 않으면 반복하지 않는다
위의 예제에서, i의 값은 15로, while의 조건인 i<10를 만족하지 않지만, do로 인해서
한번은 실행 되기때문에, 프로그램을 실행해보면 15라는 값이 출력된다

■■■■■■■■■■■■■■■■■■try와 catch■■■■■■■■■■■■■■■■■■
File file = new Scanner(file);
try { Scanner sc = new Scanner(file); } //try의 {}안의 코드를 실행시킨다
catch (FileNotFoundException e) { System.out.println("파일을 읽어오던 중 오류발생"); } //try의 코드를 실행시켰는데 catch의 괄호안에 등록된 오류가 발생할경우 {}안의 코드를 실행시킨다.

switch문, 배열, 메소드오버로딩 오버라이딩, 클래스상속

■■■■■■■■■■■■■■■■■■배열■■■■■■■■■■■■■■■■■■
자바에선 배열을 객체로 취급한다.
자바의 배열 사용과정은 2단계이다.
1.배열선언 : int a[]; 또는 int[] a;
2.배열객체생성 : a = new int[5];

int a [] = new int[5];
이런식으로 선언과 객체생성을 동시에 할 수도있다.

자바의 배열은 한번 크기가 정해지면 바꿀 수 없다
배열이름.length 는 배열 원소의 갯수를 의미한다

int a [5];
C언어와 마찬가지로 배열이름 a는 배열의 시작주소값을 의미한다.
(배열의 이름(a)이 저장되는 주소와 배열이 시작되는 저장주소(a[0])는 서로 다른 주소이다.)
그리고 시작주소가 100이면 int타입(4바이트) 5칸 배열이니 100~116 까지의 연속된 공간에 차례로 저장된다.
0번째 - 100 1번째 - 104 2번째 - 108....
총 다섯칸이니 4바이트x5 = 20바이트의 공간을 사용한다.

int a[];
이처럼 배열을 선언할때 크기를 정해 주지 않으면 원소의 갯수를 알 수 없으므로
배열의 원소를 메모리에 할당할 수 없고, 따라서 배열의 시작 주소 또한 결정되지 않았으므로 null이 들어간다.
따라서 배열이 메모리에 할당되는 시점은 배열 선언이 아닌 배열객체 생성시이다.
(아까 int a [5]; 는 시작 주소가 100이라고 가정했었는데 여기선 시작주소에 null이 들어감)
이후에 a = new int[5] ; 이런 식으로 배열 객체를 생성해야함

int [] a = {1, 2, 3, 4, 5};
이렇게 배열선언과 동시에 초기화하면 배열 객체를 생성할 필요없다

int a [] = new int[5];
a = new int[3];
이렇게 실행하면 실행이된다. 왜냐면 a의 배열의 크기가 변한것이 아니라 새로운 배열로 덮어씌워 진것이기 때문이다.
따라서 처음 5칸 짜리 배열이었을때 값을 저장해놨다면 그 값들은 삭제된다.

a는 [2][2]의 2차원 배열, b는 [2]의 1차원 배열이라할때,
a[0] = b;
이런식으로 2차원 배열에 1차원 배열 대입 가능하다.
a[0]는 a라는 2차원 배열에 포함된 1차원 배열이기 때문에 1차원배열을 그대로 넣을 수 있다.
만약 b가 [2][2]의 2차원 배열이라면 a = b; 이런식으로 2차원배열에 2차원배열을 대입한다.

■■■■■■■■■■■■■■■■■■형변환■■■■■■■■■■■■■■■■■■
1. 묵시적 형변환

  • 형변환 연산자를 사용하지 않아도 자동으로 이루어지는 형변환을 의미한다.
  • 더 넓은 범위로 데이터를 저장하기 때문에, 데이터의 손실이 없다.
    ex) int a=5; double b = a;
  1. 명시적 형변환
  • 데이터의 손실이 발생할 수 있으므로 명시적으로 형변환 연산자를 사용해야 한다.
  • 더 큰 범위에서 작은 범위로의 형변환을 의미한다.
    ex) dobule a = 42.195; int b = (int)a;

---------------------------------객체의 형변환----------------------------------
객체의 형변환 시 조건

  • 왼쪽 항과 오른쪽 항은 서로 상속관계에 있어야 한다.
  • 부모 타입의 객체 = 자식 타입의 객체, 이를 묵시적 형변환이라고 한다.
  • 자식 타입의 객체 = (자식 타입) 부모타입, 이를 명시적 형변환이라고 한다.

■■■■■■■■■■■■■■■■■■패키지■■■■■■■■■■■■■■■■■■
연관된 클래스나 인터페이스들을 하나로 묶어 놓은 주머니
C언어의 라이브러리와 동일 ex) include<stdio.h>

패키지 종류
java.lang - 자바의 기본적인 기능제공 자동으로 자바 프로그램에 포함됨
java.util - 유용한 유틸리티 클래스 제공
java.io - 입출력 기능 제공
java.applet - 애플릿 프로그램과 연관된 클래스 제공
java.awt - 그래피컬 사용자 인터페이스 (GUI)를 구축하기 위한 컴포넌트 제공
java.awt.event - awt패키지 안에 또다시 event패키기가 있음. awt컴포넌트의 이벤트를 제어하는 패키지
java.net - 네트워킹과 관련된 기능을 제공, telnet, ftp, http 같은 프로토콜 사용을 위한 클래스 제공

패키지는 클래스 이름 사이의 충돌 문제를 해결할 수 있다.
ex)
graphic 패키지 - Print클래스 , Color클래스
text 패키지 - Print클래스, Font클래스
Print p = new Print(); <- 어느 패키지의 Print인지 알 수 없다.
graphic.Print p = new graphic.Print();
text.Print p2 = new text.Print(); //이렇게 패키지 이름을 적어서 구분가능하다

패키지를 사용하는 방법
1. import 문 사용
형식 : import 패키지명.클래스명;
ex)
import java.applet.; <- 은 해당 패키지 내의 모든 클래스를 사용한다는 뜻
import java.applet.Applet; <- 패키지 내에서 Applet 클래스만 사용

  1. 절대경로명 사용
    import문을 쓰지 않고 패키지.클래스이름 으로 직접 표현한다.
    형식 : 패키지명.클래스명
    ex)
    java.util.Date d = new java.util.Date(); <- import를 안했으므로 패키지명을 모두 써야함
    text.Print p1;
    graphic.Print p2;
    여러 패키지 사용 중 패키지 내에 이름이 같은 클래스를 사용할 때 유용하다.

사용자 정의 패키지
1. 패키지 경로를 설정
2. 만들려 하는 패키지명으로 폴더를 만든다.
3. 만든 폴더 내에 클래스 파일들을 하나씩 만들어 넣는다.
4. 만든 사용자 정의 패키지를 사용한다.

■■■■■■■■■■■■■■■■■■sql연결■■■■■■■■■■■■■■■■■■
import java.sql.*; 해야함

try{ //연결이 실패할 수도 있으므로 반드시 예외처리로 해줘야함
Class.forName("com.mysql.cj.jdbc.Driver"); //mysql jdbc driver 연결
System.out.println("드라이버 로드 완료");
}
catch (ClassNotFoundException e) {
System.out.println("드라이버 로드에 실패했습니다.");
}

try{ //마찬가지로 예외처리 해줘야함,
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/[DB이름]?serverTimezone=UTC", "[아이디]", "[비밀번호]"); //한줄로 작성해야함
System.out.println("DB연결 완료");
Statement dbst = con.creatStatement(); //자바에선 질의문도 객체로 처리, Statement가 질의어를 처리하는 클래스, createStatement는 질의어를 생성해 적용하는것
}
catch (SQLException e) {
System.out.println("SQLException : " +e.getMessage());
}

//↓이런식으로 쿼리문을 string에 저장한다
String strSql = "INSERT INTO student_info (id, passwd) VALUES (“ +"'"+t_id+"','"+t_passwd+“’, ‘”+"');";

-----------DB연동 끊기--------------
DB사용이 끝났으면 연동을 끊어준다
dbst.close(); //DB연동 끊기
con.close();

---------------쿼리문 실행----------------
쿼리문을 실행하는 메소드 3종류
●Statement객체.execute
●Statement객체.executeQuery
●Statement객체.executeUpdate

▶execute
1. 수행결과로 Boolean 타입의 값을 반환한다
2. 모든 구문을 수행할 수 있다.
3. 리턴값이 ResultSet 일 경우에는 true, 이 외의 경우에는 false 로 출력됩니다.
4. 리턴값이 ResultSet 이라고 하여 ResultSet 객체에 결과값을 담을 수 없습니다.
ex) boolean result = strSql.execute(); //strSql = 쿼리문 저장한 String

▶executeQuery
1. 수행결과로 ResultSet 객체의 값을 반환
2. SELECT 구문을 수행할 때 사용되는 함수 (받아올 결과값이 있을 때 사용한다)
ex)ResultSet result = strSql.executeQuery(); //strSql에 담긴 쿼리문을 실행하고 그 결과를 ResultSet 객체에 받아온다.

쿼리문의 결과값 ↓
++++++++++++++++
name num ←(속성)
홍길동 1010
김철수 1065
+++++++++++++++++
처음 result 값을 받아온 상태는 포인터가 결과값(튜플)의 0번째를 가르키고 있다.
이때 바로 get메소드를 쓰면 값을 읽어올 수 없다.
따라서 result.next() 메소드로 이 포인터를 한칸 내린후 getInt, getString 등의 메소드로 값을 받아온다
next()를 한번 한 후에 result.getString(1)을 했다면 "홍길동"을 받아온다.
getString(), getInt() 등의 메소드를 쓸 때, 매개변수는 튜플의 칼럼(속성)을 나타낸다.
값으로 1을 넣으면 name 속성, 2를 넣으면 num 속성을 뜻한다.

ex) next()메소드는 다음과 같이 사용할 수도 있다.
if(result.next()){
결과 값이 있으면 실행할 코드.....
}
이렇게 조건문안에 넣어놓으면, 결과값에서 포인터를 한칸 내렸을 때, 결과값이 존재하면 true를, 없으면 false를 반환한다.
즉 결과 값이 있는지 없는지 확인 할 수 있다.

while(result.next()) 와 같이 쓴다면 결과값이 끝날때까지(결과값 튜플의 갯수) while 반복문을 계속 실행하게 된다.

▶executeUpdate
1. 수행결과로 Int 타입의 값을 반환한다.
2. SELECT 구문을 제외한 다른 구문을 수행할 때 사용되는 함수 (결과값이 없는 update, insert, delete등의 작업을 할 때 사용한다)
3. INSERT / DELETE / UPDATE 관련 구문에서는 반영된 레코드의 건수를 반환한다
4. CREATE / DROP 관련 구문에서는 -1 을 반환한다
ex) dbst.executeUpdate(strSql); //질의문 실행

■■■■■■■■■■■■■■■■■■GUI■■■■■■■■■■■■■■■■■■

--------------------DefaultTableModel 메소드---------------------

  • TableModel 인터페이스 = 최상위 인터페이스
  • 메소드 : addTableModelListener(TableModelListener)
    getColumnClass(int) -> 해당 컬럼의 타입 반환
    getColumnCount() ->컬럼 총 개수 반환
    getColumnName(int) -> 해당 컬럼의 이름 반환
    getRowCount() -> 총 행 개수 반환
    getValueAt(int,int) -> 해당열과 행 위치에 있는 데이터 반환
    setValueAt(Object,int,int) -> 특정 위치번째에 원하는 오브젝트 타입의 개체를 세팅 시킬수 있음
    즉. 첫번째 지정한 오브젝트는 밸류 임
  • AbstractTableModel = 테이블 모델 상속받은, abstractclass
    findColumn(String) - > 해당 벨류가 있는 컬럼을 찾을 수 있음.
    기타 상속 메소드
  • DefaultTableModel = abstractTabelModel 을 상속받은 클래스
    addColumn(컬럼명) -> 컬럼 추가
    addColumn(컬럼명,배열) -> 컬럼추가 및 데이터 추가 ( 벡터 가능 )
    addRow(배열) -> 배열 단위로 행 추가
    getDataVector() -> 테이블 내 데이터를 벡터로 뽑아냄
    insertRow(행번호,배열) -> 지정하는 행 번호 위치에 데이터를 삽입함
    moveRow(시작행번호,마지막행번호,이동할행번호) - > 해당 행 번호 데이터를, 이동할 행번호로 이동
    removeRow(행번호) -> 해당 행 번호 데이터를 삭제
    setColumnIdentifiers(배열 ) -> 컬럼명을, 해당 배열로 치환 시킴

기타

HashSet
중복 허용X, 순서 랜덤
HashMap
파이썬 딕셔너리와 비슷, 키와 값으로 이루어짐, 이미 있는 키를 추가하면 기존 값은 새 값으로 대체됨

HashSet<자료형객체> abc = new HashSet<>(); //int같은 기본자료형 말고 Integer, String같은 자료형 객체
abc.add(값); //abd메소드로 추가 가능
abc.remove(값); //remove메소드로 삭제가능
abc.size() //크기를 리턴. 배열의 length와 같은 기능
abc.contains(값); //값을 검색하여 있으면 true, 없으면 false 리턴

HashMap<키, 값> map1 = new HashMap<키, 값>(); //HashMap생성
HashMap<키, 값> map2 = new HashMap<>(); //new에서 타입 파라미터 생략가능
HashMap<String,String> map3 = new HashMap<>(map1); //map1의 모든 값을 가진 HashMap생성
HashMap<String,String> map4 = new HashMap<>(10); //초기 용량(capacity)지정
HashMap<String,String> map5 = new HashMap<>(10, 0.7f); //초기 capacity,load factor지정
HashMap<String,String> map6 = new HashMap<String,String>(){{ //초기값 지정
put(키, 값); //해시맵에 추가
map.remove(키); //해당 키 제거
map.clear(); //모든 값 제거
map.get(키); //해당 키의 값 가져오기
map.values(); //값 모두 가져오기 (Collection 타입 리턴)
getOrDefault(키, 기본값); //맵에서 주어진 키(key)가 존재하면 해당 값을 반환, 없으면 기본값으로 맵에 추가
System.out.println(map); //전체 출력 : {1=사과, 2=바나나, 3=포도}
}};

entrySet() 활용

for (Entry<Integer, String> entry : map.entrySet()) {
    System.out.println("[Key]:" + entry.getKey() + " [Value]:" + entry.getValue());
}

entrySet()은 key와 value 모두가 필요할 경우 사용하며 keySet()은 key 값만 필요할 경우 사용

map.forEach((key, value) -> { System.out.println(key + " : " + value); });
Java 8 이후로는 forEach 문을 사용하여 map을 순회하면서 key와  value를 출력할 수 있다.

Arrays.sort(배열) //정렬함수
Arrays.asList() //배열을 리스트로 만들어줌
Arrays.fill(배열, 값); // 배열의 모든 요소를 해당 값으로 초기화해줌
Integer max = Collections.max(리스트); //리스트 내에서 최댓값을 찾아줌
Integer min = Collections.min(리스트); //리스트 내에서 최솟값을 찾아줌

배열을 요소로 가지는 리스트에서, 배열의 특정 요소를 기준으로 리스트 내의 최솟값, 최댓값 찾기

List<int[]> list = new ArrayList<>();
// 리스트에 배열 추가

int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int[] arr : list) {
    max = Math.max(max, arr[0]); // 배열의 첫 번째 요소를 기준으로 최댓값 갱신
    min = Math.min(min, arr[0]); // 배열의 첫 번째 요소를 기준으로 최솟값 갱신
}

배열을 요소로 가지는 리스트에서, 배열의 특정 값을 기준으로 리스트를 정렬하는 법

배열의 두 번째 요소를 기준으로 정렬

        Collections.sort(list, new Comparator<int[]>() {
            @Override
            public int compare(int[] arr1, int[] arr2) {
                return Integer.compare(arr1[1], arr2[1]); //기준을 변경하려면 여기 arr1, arr2의 인덱스 값을 수정
            }
        });

문자열.charAt(인덱스) //해당 인덱스의 문자 가져옴
문자열.substring(인덱스) //해당 인덱스부터 끝까지 문자열 가져옴
문자열.substring(인덱스1, 인덱스2) //인덱스1부터 인덱스2 바로 전까지 가져옴

다중 반복문 벗어나는 법

public class Main {
    public static void main(String[] args) {
        outerLoop:
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                if (i * j > 6) {
                    System.out.println("Breaking at i = " + i + ", j = " + j);
                    break outerLoop;
                }
            }
        }
    }
}

String s[] = {"1", "2", "3"};
"문자열".length() //문자열의 길이
s.length // 배열 자체의 길이를 구할 땐 괄호 안붙임
s[0].length() //배열 안의 요소의 길이를 구할 땐 괄호 붙여야함

문자열.startsWith(접두사) //문자열이 해당 접두사로 시작하는지 확인하여 true, false반환

Queue사용
Queue queue = new LinkedList<>(); //LinkedList는 큐를 구현하기 위해 사용, LinkedList 클래스는 Queue 인터페이스의 구현체이며, 큐로 사용할 때 유용
queue.offer(값); //요소를 큐에 추가 후, 성공하면 true, 실패하면 false반환
int frontElement = queue.poll(); //큐의 맨 앞 요소를 제거하고 반환, 큐가 비어있을 경우 null을 반환
int endElement = queue.remove(); //큐의 제일 뒤 요소를 제거하고 반환
int frontElement = queue.peek(); //큐의 맨 앞 요소를 반환하지만 제거하지 않음, 큐가 비어있을 경우 null을 반환
queue.isEmpty(); //큐 비었으면 true, 아니면 false반환
int size = queue.size(); //큐의 크기 확인

List
순서가 있는 데이터 집합, 크기가 가변적, 요소 추가와 제거 가능
ArrayList, LinkedList 등이 있음

List list = new ArrayList<>(); //리스트 생성
int size(): 리스트의 크기를 반환합니다.
boolean isEmpty(): 리스트가 비어 있는지 여부를 반환합니다.
boolean contains(Object o): 리스트가 지정된 요소를 포함하고 있는지 여부를 반환합니다.
boolean add(E e): 리스트에 지정된 요소를 추가합니다.
boolean remove(Object o): 리스트에서 지정된 요소를 제거합니다.
void clear(): 리스트의 모든 요소를 제거합니다.
E get(int index): 리스트에서 지정된 위치의 요소를 반환합니다.
E set(int index, E element): 리스트에서 지정된 위치의 요소를 새 요소로 대체합니다.
void add(int index, E element): 리스트의 지정된 위치에 요소를 삽입합니다.
E remove(int index): 리스트에서 지정된 위치의 요소를 제거하고 반환합니다.
int indexOf(Object o): 리스트에서 지정된 요소의 인덱스를 반환합니다. 처음으로 나타나는 위치의 인덱스를 반환합니다.
int lastIndexOf(Object o): 리스트에서 지정된 요소의 인덱스를 반환합니다. 마지막으로 나타나는 위치의 인덱스를 반환합니다.
List subList(int fromIndex, int toIndex): 리스트의 부분 리스트를 반환합니다.
boolean addAll(Collection<? extends E> c): 지정된 컬렉션의 모든 요소를 리스트에 추가합니다.
boolean removeAll(Collection<?> c): 지정된 컬렉션에 포함된 모든 요소를 리스트에서 제거합니다.
boolean retainAll(Collection<?> c): 지정된 컬렉션에 포함된 요소만을 리스트에 유지하고 나머지 요소는 제거합니다.
boolean containsAll(Collection<?> c): 리스트가 지정된 컬렉션의 모든 요소를 포함하고 있는지 여부를 반환합니다.
Object[] toArray(): 리스트의 요소를 배열로 반환합니다.
T[] toArray(T[] a): 리스트의 요소를 지정된 배열에 복사합니다.

배열 값 전부 출력하기
int[] arr = {1, 2, 3, 4, 5};
System.out.println(Arrays.toString(arr));
Arrays.stream(arr).forEach(num -> System.out.print(num + " "));

LinkedList
add(E e): LinkedList의 끝에 요소를 추가합니다.
addFirst(E e): LinkedList의 시작 부분에 요소를 추가합니다.
addLast(E e): LinkedList의 끝에 요소를 추가합니다. add()와 동일합니다.
poll(): LinkedList의 첫 번째 요소를 제거하고 반환합니다. 없으면 null반환
pollFirst(): LinkedList의 첫 번째 요소를 제거하고 반환합니다. poll()와 동일합니다. 없으면 null반환
pollLast(): LinkedList의 마지막 요소를 제거하고 반환합니다. 없으면 null반환
get(int index): 주어진 인덱스에 해당하는 요소를 반환합니다.
getFirst(): 첫번째 요소를 제거하지 않고 반환. 없으면 NoSuchElementException예외발생
getLast(): 마지막 요소를 제거하지 않고 반환. 없으면 NoSuchElementException예외발생
set(int index, E element): 주어진 인덱스의 위치에 새로운 요소를 설정합니다.
size(): LinkedList의 요소 수를 반환합니다.
isEmpty(): LinkedList가 비어 있는지 여부를 반환합니다.
clear(): LinkedList의 모든 요소를 제거합니다.
contains(Object o): 지정된 요소가 LinkedList에 포함되어 있는지 여부를 확인합니다.
indexOf(Object o): 지정된 요소의 첫 번째 발생 위치를 반환합니다.
lastIndexOf(Object o): 지정된 요소의 마지막 발생 위치를 반환합니다.
toArray(): LinkedList의 요소를 배열로 반환합니다.

PriorityQueue (힙)

내부적으로 힙 자료구조를 사용하여 원소를 정렬하여 가장 작은 원소가 항상 큐 앞에 위치한다.
PriorityQueue pq = new PriorityQueue<>(); //기본적으로 최소힙으로 생성됨

최대힙으로 만드는 법
PriorityQueue maxHeap = new PriorityQueue<>(Collections.reverseOrder());

메소드
add(E e) 또는 offer(E e): 지정된 요소를 큐에 추가합니다.
remove() 또는 poll(): 큐에서 요소를 제거하고 반환합니다. 큐가 비어있으면 null을 반환합니다.
element() 또는 peek(): 큐의 맨 위에 있는 요소를 반환합니다. 큐가 비어있으면 예외를 발생시킵니다.
size(): 큐의 요소 수를 반환합니다.
isEmpty(): 큐가 비어있는지 여부를 확인합니다.
clear(): 큐의 모든 요소를 제거합니다.
toArray(): 큐의 요소를 배열로 반환합니다.

배열을 요소로 갖는 힙에서, 배열의 특정 요소를 기준으로 정렬시키기

import java.util.PriorityQueue;

//해당 배열을 클래스로 만듦
class Job implements Comparable<Job> {
    int[] job;

    public Job(int[] job) {
        this.job = job;
    }

    // Comparable 인터페이스의 compareTo 메서드를 오버라이드하여 우선순위를 정의합니다.
    @Override
    public int compareTo(Job other) {
        // 요청 시점이 빠른 순서대로 정렬됩니다.
        return Integer.compare(this.job[0], other.job[0]); //a와 b를 비교하여 a가 작으면 음수, 같으면 0, a가 크면 양수를 반환. 
       //배열의 다른 요소를 기준으로 정렬하고 싶다면 this.job[0], other.job[0]의 인덱스 수정.
       //최대힙으로 동작하게 하고 싶으면 other.job[0], this.job[0] 순서로 바꿈
    }
}

public class Main {
    public static void main(String[] args) {
        PriorityQueue<Job> pq = new PriorityQueue<>();

        // Job 객체를 생성하여 PriorityQueue에 추가합니다.
        pq.add(new Job(new int[]{3, 10}));
        pq.add(new Job(new int[]{1, 20}));
        pq.add(new Job(new int[]{2, 30}));

        // PriorityQueue에서 요소를 하나씩 꺼내어 출력합니다.
        while (!pq.isEmpty()) {
            Job job = pq.poll();
            System.out.println("Request time: " + job.job[0] + ", Remaining time: " + job.job[1]);
        }
    }
}
profile
주니어 개발자

0개의 댓글