no image
[C++] 백준 13단계 - 1181번 문제 (단어 정렬)
문제설명 소스코드 #include #include using namespace std; bool compare(string a, string b) { if (a.length() != b.length()) return a.length() > N; string* arr = new string[N]; for (int i = 0; i > arr[i]; sort(arr, arr + N, compare); for (int i = 0; i < ..
2023.07.20
no image
[JAVA] 자바 표준 모듈, java.base 모듈
이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 자바 표준 모듈 표준 라이브러리는 Java 9부터 모듈화가 되어 아래의 그림처럼 Java 17 표준 모듈이 완성되었다. 화살표는 모듈 간의 의존 관계를 표시한다. java.base는 모든 모듈이 의존하는 기본이자 핵심 모듈이다. 또한 requires 하지 않아도 사용할 수 있다. java.base 모듈에는 java.lang, java.util, java.io 등의 핵심 패키지가 있고, java.lang을 제외하고 import 해서 사용할 수 있다. java.se는 JDK가 제공하는 모든 모듈을 제공하는 집합 모듈이다. 표준 라이브러리를 제한 없이 사용하고 싶을 경우에는 java.se를..
2023.07.20
no image
[C++] 백준 13단계 - 18870번 문제 (좌표 압축)
문제설명 소스코드 #include #include #include using namespace std; int main() { ios_base::sync_with_stdio(false); //표준 스트림 동기화 해제 cin.tie(NULL); //입력과 출력 연결 끊기 vector original, tmp; int N; cin >> N; for (int i = 0; i > input; original.push_back(input); //원본 벡터에 입력받음 tmp.push_back(input); //임시 벡터에 입력받음 } sort(tmp.begin(), tmp.end()); //임시 벡터 정렬 tmp.erase(unique(tmp.begin(), tmp..
2023.07.19
no image
[C++] 백준 13단계 - 11651번 문제 (좌표 정렬하기 2)
문제설명 소스코드 #include #include using namespace std; class XY { public: int x; int y; bool operator y y == arr.y) && (this->x > N; XY* arr = new XY[N]; for (int i = 0; i < N; ++i) cin ..
2023.07.19
no image
[JAVA] 라이브러리 생성 및 불러오기
이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 라이브러리는 프로그램 개발 시 활용할 수 있는 클래스와 인터페이스들을 모아 놓은 것을 말한다. 일반적으로 JAR(Java ARchive) 압축파일 형태로 존재한다. JAR 파일에는 클래스와 인터페이스의 바이트 코드 파일(~.class)들이 압축되어 있다. 라이브러리를 사용하면 개발 시간이 단축되고 유지보수가 용이하다. 나만의 라이브러리 생성하기 1. 새 프로젝트 생성 주의할 점은 Create module-info,java file에 체크를 하지 않는 것이다. 프로젝트 이름은 my_lib로 하였고, 패키지 pack1과 pack2를 생성하고 각 패키지에 A와 B 클래스를 선언했다. 2. ..
2023.07.19
no image
[C++] 백준 13단계 - 10814번 문제 (나이순 정렬)
문제설명 소스코드 sort() 이용(quick sort) #include #include using namespace std; class name_age { public: string name; int age; int idx; bool operator age != arr.age) return this->age idx > N; name_age* arr = new name_age[N]; fo..
2023.07.18
no image
[C++] 백준 13단계 - 11650번 문제 (좌표 정렬하기)
문제설명 소스코드 #include #include using namespace std; class XY { public: int x; int y; bool operator x x == arr.x) && (this->y > N; XY* arr = new XY[N]; for (int i = 0; i < N; ++i) cin ..
2023.07.18
no image
[JAVA] 중첩 인터페이스 (nested interface)
이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 중첩 인터페이스 중첩 인터페이스는 클래스의 멤버로 선언된 인터페이스를 뜻한다. 인터페이스를 클래스 내부에 선언하는 이유는 해당 클래스와 긴밀한 관계이기 때문이다. 즉, 인터페이스 외부의 클래스가 존재하지 않는다면 해당 인터페이스는 쓸모가 없기 때문이다. 중첩 인터페이스는 아래와 같이 선언된다. class A{ [public | private] | [static] interface B{ //상수 필드 //추상 메소드 //디폴트 메소드 //정적 메소드 } } 외부의 접근을 막지 않으려면 public A 클래스 내부에서만 사용하려면 private 접근 제한자를 붙이지 않으면 같은 패키지 안..
2023.07.18

문제설명

 

소스코드

#include <iostream>
#include <algorithm>
using namespace std;
bool compare(string a, string b)
{
	if (a.length() != b.length()) return a.length() < b.length();
	else return a < b;
}
int main()
{
	ios_base::sync_with_stdio(false); //표준 스트림 동기화 해제
	cin.tie(NULL); //입력과 출력 연결 끊기
	int N;
	cin >> N;
	string* arr = new string[N];
	for (int i = 0; i < N; ++i) cin >> arr[i];
	sort(arr, arr + N, compare);
	for (int i = 0; i < N; ++i)
	{
		if (arr[i] == arr[i + 1]) continue;
		else cout << arr[i] << '\n';
	}
}

 

설명

  • 기본적으로 algorithm 라이브러리의 sort() 함수를 사용한다.
  • sort() 함수의 세 번째 매개값으로 compare() 함수를 넘긴다.
  • 길이가 같지 않으면 길이가 짧은 순으로 정렬하고, 길이가 같다면 사전순으로 정렬한다.
  • 표준 스트림 동기화 해제, 입출력 연결 끊기, endl 대신 '\n'사용 -> 시간초과 방지

이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 


자바 표준 모듈

표준 라이브러리는 Java 9부터 모듈화가 되어 아래의 그림처럼 Java 17 표준 모듈이 완성되었다.

화살표는 모듈 간의 의존 관계를 표시한다.

일부의 그림이다. 전체를 표시하지 않았다.

  • java.base는 모든 모듈이 의존하는 기본이자 핵심 모듈이다. 또한 requires 하지 않아도 사용할 수 있다.
  • java.base 모듈에는 java.lang, java.util, java.io 등의 핵심 패키지가 있고, java.lang을 제외하고 import 해서 사용할 수 있다.

 

  • java.se는 JDK가 제공하는 모든 모듈을 제공하는 집합 모듈이다.
  • 표준 라이브러리를 제한 없이 사용하고 싶을 경우에는 java.se를 모듈 기술자에 requires하면 된다.
  • 모듈 기술자가 없는 프로젝트를 만들면 모듈로 인식되지 않기 때문에 자바 표준 라이브러리를 제한 없이 사용할 수 있다.

 

자바 표준 모듈은 왜 이렇게 많은 모듈로 이루어졌는가?

모듈이라는 개념이 없었을 때는 아무런 제한 없이 모든 기능을 쓸 수 있었지만, 단점이 하나 있었다.

바로, 아무리 간단한 프로그램일지라도 약 40MB의 용량을 차지한다는 것이다.

따라서 임베디드 기기에서는 자바 프로그램 실행 자체가 되질 않았다.

Java 8 이전 버전까지는 프로그램이 표준 라이브러리의 5%만 사용하는데도 실행하려면 전체 표준 라이브러리가 갖추어진 자바 실행 환경(JRE)이 필요했다.
따라서 모듈화를 한 이유는 필요한 모듈만으로 구성된 작은 사이즈의 JRE를 만들기 위해서이다.

 

이런 문제점이 계속 지적되어 모듈이라는 개념이 도입되었고, 세세하게 분해가 되어서 필요한 모듈만 쓰면 되기 때문에 프로그램의 용량을 줄일 수 있게 되었다.

 


java.base 모듈

  • java.base는 모든 모듈이 의존하는 기본 모듈로, 모듈 중 유일하게 requires하지 않아도 사용할 수 있다.
  • 이 모듈에 포함되어 있는 패키지는 대부분 자바 프로그램에서 많이 사용하는 것들이다.

java.base 모듈에 포함된 주요 패키지와 용도

우리가 흔히 사용하는 String, System, Integer, Double, Exception, RuntimeException 등의 클래스는 java.lang에 있고, 키보드 입력을 위해 사용한 Scanner는 java.util 패키지에 있다.

 

java.lang은 자바 언어의 기본적인 클래스를 담고 있는 패키지로, 이 패키지에 있는 클래스와 인터페이스는 import 없이 사용할 수 있다.

java.lang 패키지에 포함된 주요 클래스와 용도

문제설명

 

소스코드

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
	ios_base::sync_with_stdio(false); //표준 스트림 동기화 해제
	cin.tie(NULL); //입력과 출력 연결 끊기
	vector<int> original, tmp;
	int N;
	cin >> N;
	for (int i = 0; i < N; i++)
	{
		int input;
		cin >> input;
		original.push_back(input); //원본 벡터에 입력받음
		tmp.push_back(input); //임시 벡터에 입력받음
	}
	sort(tmp.begin(), tmp.end()); //임시 벡터 정렬
	tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end()); //임시 벡터 중복원소 제거
	for (int i = 0; i < N; ++i) cout << lower_bound(tmp.begin(), tmp.end(), original[i]) - tmp.begin() << ' '; //원본 벡터의 i번째 원소보다 작은 임시벡터를 출력
}

 

설명

  1. 원본 벡터와 임시 벡터에 모두 입력을 받음
  2. 임시 벡터 정렬(sort 함수 이용)
  3. 임시 벡터의 중복 원소를 제거한다.
    • unique(tmp.begin(), tmp.end()) -> 중복된 원소를 뒤로 밀어버려서 벡터 뒤엔 중복된 원소만 남게됨. 이후 중복된 원소의 첫 번째 원소의 주소를 리턴
      tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end()) -> 중복된 원소의 첫 번째 부터 벡터의 마지막까지를 지워버림
  4. 원본벡터[i] 보다 작은 임시 벡터의 개수를 출력
    • lower_bound() 함수는 순차 탐색이 아니라 이진 탐색이기 때문에 정렬이 되어 있어야하고, 때문에 속도가 순차 탐색보다 훨씬 빠르다.

 

문제설명

 

소스코드

#include <iostream>
#include <algorithm>
using namespace std;
class XY {
public:
	int x; int y;
	bool operator < (XY& arr) { 
		if (this->y < arr.y) return true;
		else
		{
			if ((this->y == arr.y) && (this->x < arr.x)) return true;
			else return false;
		}
	}
};
int main() {
	ios_base::sync_with_stdio(false); //표준 스트림 동기화 해제
	cin.tie(NULL); //입력과 출력 연결 끊기
	int N;
	cin >> N;
	XY* arr = new XY[N];
	for (int i = 0; i < N; ++i) cin >> arr[i].x >> arr[i].y;
	sort(arr, arr + N);
	for (int i = 0; i < N; ++i) cout << arr[i].x << " " << arr[i].y << '\n';
}

 

설명

  • 클래스 배열로 좌표를 나타냄
  • algorithm 라이브러리의 sort() 함수를 올바르게 실행하려면 클래스 내부의 연산자 < 의 재정의(오버라이딩)가 필요함
  • y좌표가 작으면 무조건 true를 리턴하고(오름차순)
    y좌표가 같고 x가 작으면 true를 리턴한다(오름차순)
    이외의 경우는 false를 리턴한다
  • 표준 스트림 동기화 해제, 입출력 연결 끊기, endl 대신 '\n'을 사용하여 시간초과를 방지를 한다.

이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 


  • 라이브러리는 프로그램 개발 시 활용할 수 있는 클래스와 인터페이스들을 모아 놓은 것을 말한다.
  • 일반적으로 JAR(Java ARchive) 압축파일 형태로 존재한다.
  • JAR 파일에는 클래스와 인터페이스의 바이트 코드 파일(~.class)들이 압축되어 있다.
  • 라이브러리를 사용하면 개발 시간이 단축되고 유지보수가 용이하다.

 

나만의 라이브러리 생성하기

1. 새 프로젝트 생성

주의할 점은 Create module-info,java file에 체크를 하지 않는 것이다.

프로젝트 이름은 my_lib로 하였고, 패키지 pack1과 pack2를 생성하고 각 패키지에 A와 B 클래스를 선언했다.

 

2. 패키지 익스플로러에서 dist 폴더를 생성한다.

 

3. 프로젝트 선택 -> 마우스 우클릭 -> Export 클릭

 

4. java 항목을 확장하면 보이는 JAR file을 선택 -> Next 버튼 클릭

 

5. 라이브러리를 만들고픈 프로젝트를 확장한 후 그 안에 있는 src 폴더만 체크하고 나머지는 모두 체크 해제한다.

 

6. Select the export desitination에서 Browse 클릭

 

7. 아까 dist 폴더를 만들었던 곳으로 이동 -> 라이브러리 이름 지정 -> Finish 버튼 클릭

 

8. JAR 파일이 생성됨

 


 

라이브러리 불러오기

1. 라이브러리를 불러올 프로젝트 선택 -> 마우스 우클릭 -> Build path -> Configure Build Path 클릭

 

2. Libaraies 탭 -> Classpath 선택 -> 오른쪽 Add External JARs 버튼 클릭

 

3. 불러오고픈 라이브러리 선택 -> apply and close 클릭

 

4. 해당 패키지를 import 하고 사용하면 된다.

 

문제설명

 

소스코드

sort() 이용(quick sort)

#include <iostream>
#include <algorithm>
using namespace std;
class name_age {
public:
	string name;
	int age;
	int idx;
	bool operator < (name_age& arr) { 
		if (this->age != arr.age) return this->age < arr.age;
		else return this->idx < arr.idx;
	}
};
int main()
{
	ios_base::sync_with_stdio(false); //표준 스트림 동기화 해제
	cin.tie(NULL); //입력과 출력 연결 끊기
	int N;
	cin >> N;
	name_age* arr = new name_age[N];
	for (int i = 0; i < N; ++i)
	{
		cin >> arr[i].age >> arr[i].name;
		arr[i].idx = i;
	}
	sort(arr, arr + N);
	for (int i = 0; i < N; ++i) cout << arr[i].age << " " << arr[i].name << '\n';
}

 

stable_sort() 이용(merge sort)

#include <iostream>
#include <algorithm>
using namespace std;
class name_age {
public:
	string name;
	int age;
};
bool compare(const name_age& a, const name_age& b) { 
	if (a.age != b.age) return a.age < b.age;
	else return false;
}
int main()
{
	ios_base::sync_with_stdio(false); //표준 스트림 동기화 해제
	cin.tie(NULL); //입력과 출력 연결 끊기
	int N;
	cin >> N;
	name_age* arr = new name_age[N];
	for (int i = 0; i < N; ++i) cin >> arr[i].age >> arr[i].name;
	stable_sort(arr, arr + N, compare);
	for (int i = 0; i < N; ++i) cout << arr[i].age << " " << arr[i].name << '\n';
}

 

설명

  • sort() : 동일한 값의 요소들에 대해, 두 요소가 기존에 가지고 있던 순서를 보장하지 않는다.
    따라서 입력받은 순서를 기억해서 따로 정렬해야한다.(정렬 속도 상대적으로 빠름)
  • stable_sort() : 동일한 값의 요소들에 대해, 두 요소가 기존에 가지고 있던 순서를 보장한다.
    따라서 입력받은 순서를 기억하고 따로 정렬할 필요가 없다. (정렬 속도 상대적으로 느림)

문제설명

 

소스코드

#include <iostream>
#include <algorithm>
using namespace std;
class XY {
public:
	int x; int y;
	bool operator < (XY& arr) { 
		if (this->x < arr.x) return true;
		else
		{
			if ((this->x == arr.x) && (this->y < arr.y)) return true;
			else return false;
		}
	}
};
int main() {
	ios_base::sync_with_stdio(false); //표준 스트림 동기화 해제
	cin.tie(NULL); //입력과 출력 연결 끊기
	int N;
	cin >> N;
	XY* arr = new XY[N];
	for (int i = 0; i < N; ++i) cin >> arr[i].x >> arr[i].y;
	sort(arr, arr + N);
	for (int i = 0; i < N; ++i) cout << arr[i].x << " " << arr[i].y << '\n';
}

 

설명

  • 클래스 배열로 좌표를 나타냄
  • algorithm 라이브러리의 sort() 함수를 올바르게 실행하려면 클래스 내부의 연산자 < 의 재정의가 필요함
  • x좌표가 작으면 무조건 true를 리턴하고(오름차순)
    x좌표가 같고 y가 작으면 true를 리턴한다(오름차순)
    이외의 경우는 false를 리턴한다.
  • 표준 스트림 동기화 해제, 입출력 연결 끊기, endl 대신 '\n'을 사용하여 시간초과 방지를 한다.

이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 


중첩 인터페이스

중첩 인터페이스는 클래스의 멤버로 선언된 인터페이스를 뜻한다.

인터페이스를 클래스 내부에 선언하는 이유는 해당 클래스와 긴밀한 관계이기 때문이다.

즉, 인터페이스 외부의 클래스가 존재하지 않는다면 해당 인터페이스는 쓸모가 없기 때문이다.

중첩 인터페이스는 아래와 같이 선언된다.

class A{
    [public | private] | [static] interface B{
        //상수 필드
        //추상 메소드
        //디폴트 메소드
        //정적 메소드
    }
}
  • 외부의 접근을 막지 않으려면 public
  • A 클래스 내부에서만 사용하려면 private
  • 접근 제한자를 붙이지 않으면 같은 패키지 안에서만 접근 가능
  • A 객체 없이 B 인터페이스를 사용하려면 static

 

중첩 인터페이스는 안드로이드와 같은 UI 프로그램에서 이벤트를 처리할 목적으로 많이 사용된다.

예를 들어 버튼을 클릭했을 때 이벤트를 처리할 중첩 인터페이스에 어떤 구현 객체가 들어가느냐에 따라 다른 결과를 낼 수 있다.

public class Button {
	//정적 멤버 인터페이스
	public static interface ClickListener {
		//추상 메소드
		void onClick();
	}

	//필드
	private ClickListener clickListener;

	//메소드
	public void setClickListener(ClickListener clickListener) { //setter
		this.clickListener = clickListener;
	}

	public void click() {
		this.clickListener.onClick();
	}
}
  • 인터페이스 타입 필드에 접근하려면 setter를 통해 접근해야함(필드가 private으로 접근 제한이 되어있으므로)
  • setter에는 인터페이스 타입 객체가 들어올 수 있고, setter를 통해 필드에 대입되는 객체가 달라질 수 있음.
  • click() 메소드를 호출하면 setter를 통해 대입된 객체의 onClick() 메소드가 호출된다.
  • 인터페이스에 여러개의 구현 객체가 대입됨으로써 다양한 버튼 클릭 이벤트를 구현할 수 있다.(다형성)

 

public class ButtonExample {
	public static void main(String[] args) {
		//Ok 버튼 객체 생성
		Button btnOk = new Button();
		//Ok 버튼 클릭 이벤트를 처리할 ClickListener 구현 클래스(로컬 클래스)
		class OkListener implements Button.ClickListener {
			@Override
			public void onClick() {
				System.out.println("Ok 버튼을 클릭했습니다.");
			}
		}
		//Ok 버튼 객체에 ClickListener 구현 객체 주입
		btnOk.setClickListener(new OkListener());
		//Ok 버튼 클릭하기
		btnOk.click();
		//-----------------------------------------------------------------------------
		//Cancel 버튼 객체 생성
		Button btnCancel = new Button();
		//Cancel 버튼 클릭 이벤트를 처리할 ClickListener 구현 클래스(로컬 클래스)
		class CancelListener implements Button.ClickListener {
			@Override
			public void onClick() {
				System.out.println("Cancel 버튼을 클릭했습니다.");
			}
		}
		//Cancel 버튼 객체에 ClickListener 구현 객체 주입
		btnCancel.setClickListener(new CancelListener());
		//Cancel 버튼 클릭하기
		btnCancel.click();
	}
}
/*
Ok 버튼을 클릭했습니다.
Cancel 버튼을 클릭했습니다.
*/
  • 위의 코드에는 OkListener(OK 버튼)과 CancelListener(Cancel 버튼) 구현 클래스가 정의되어 있다.
  • Button 클래스 내부의 setter에 해당 구현 객체를 전달한다.
  • setter는 필드를 매개변수로 받은 객체로 대입한다.
  • click() 메소드를 호출하면 어떤 구현 객체가 대입되었느냐에 따라서 출력되는 내용이 달라진다.
구현 객체는 보통 익명 객체로 설정한다.

 


 

중첩 인터페이스에 익명 객체 대입

2023.01.13 - [프로그래밍 언어/JAVA] - [JAVA] 익명 객체(Anonymous Object)

 

[JAVA] 익명 객체(Anonymous Object)

본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다. 익명 객체 클래스를 선언할 때 일반적으로 클래스 이름과 동일한 소

rebugs.tistory.com

위에서 살펴봤던 예제는 구현 클래스를 정의하고, setter에 해당 객체를 대입하는 방법이었다.

그 방법보다 setter에 익명 구현 객체를 넘기는 방법이 많이 사용된다.

Button.java

public class Button {	
	//정적 멤버 인터페이스
	public static interface ClickListener {
		//추상 메소드
		void onClick();
	}
	
	//필드
	private ClickListener clickListener;
		
	//메소드
	public void setClickListener(ClickListener clickListener) {
		this.clickListener = clickListener;
	}
	
	public void click() {
		this.clickListener.onClick();
	}
}

 

Main.java

public class Main {
	public static void main(String[] args) {
		//Ok 버튼 객체 생성
		Button btnOk = new Button();

		//Ok 버튼 객체에 ClickListener 구현 객체 주입
		btnOk.setClickListener(new Button.ClickListener() {
			@Override
			public void onClick() {
				System.out.println("Ok 버튼을 클릭했습니다.");
			}
		});

		//Ok 버튼 클릭하기
		btnOk.click();

		//----------------------------------------------------------------------------

		//Cancel 버튼 객체 생성
		Button btnCancel = new Button();

		//Cancel 버튼 객체에 ClickListener 구현 객체 주입
		btnCancel.setClickListener(new Button.ClickListener() {
			@Override
			public void onClick() {
				System.out.println("Cancel 버튼을 클릭했습니다.");
			}
		});

		//Cancel 버튼 클릭하기
		btnCancel.click();
	}
}