no image
[Java] 백준 17단계 - 10872번 문제 (팩토리얼)(재귀X)
문제설명 소스코드 import java.util.Scanner; public class Main { public static void main(String[] args) throws Exception{ Scanner sc = new Scanner(System.in); int N = sc.nextInt(); long count = 1; if (N==0) System.out.print(1); else { for(int i = 1; i
2023.07.29
no image
[Java] 백준 17단계 - 24723번 문제 (녹색거탑)
문제설명 소스코드 import java.util.Scanner; public class Main { public static void main(String[] args) throws Exception{ Scanner sc = new Scanner(System.in); int N = sc.nextInt(); System.out.print((int)Math.pow(2, N)); } } 설명 한 층을 내려올 때마다 경우의 수는 2가지 이므로 N층을 내려올 때 경우의 수는 2^N개 이다.
2023.07.29
no image
[Java] StringBuilder 클래스, StringTokenizer 클래스
이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. String은 내부 문자열을 수정할 수 없다. 아래의 코드를 보면 다른 문자열을 결합해서 내부 문자열을 변경하는 것처럼 보이지만 사실 'ABCDEF'라는 새로운 String 객체를 생성하는 것이다. 그리고 data 변수는 새로 생성된 String 객체를 참조하게 된다. String data = "ABC"; data += "DEF"; 문자열의 + 연산은 새로운 String 객체가 생성되고 이전 객체는 계속 버려지는 것이기에 효율이 좋지 못하다. 잦은 문자열 변경 작업을 해야 한다면 String 보다는 StringBuilder를 사용하는 것이 좋다. StringBuilder 클래스 Str..
2023.07.29
no image
[Java] 백준 17단계 - 15439번 문제 (베라의 패션)
문제설명 소스코드 import java.util.Scanner; public class Main { public static void main(String[] args) throws Exception{ Scanner sc = new Scanner(System.in); int N = sc.nextInt(); System.out.print(N * (N - 1)); } } 설명 생략
2023.07.28
no image
[Java] 백준 15단계 - 2485번 문제 (가로수)
문제설명 소스코드 import java.io.BufferedReader; import java.io.InputStreamReader; public class Main { public static void main(String[] args) throws Exception{ BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); int N = Integer.parseInt(br.readLine()); int arr[] = new int[N]; //가로수의 개수 입력 받음 int minDivisor = 0; int sum = 0; for(int i = 0; i < N; ++i) arr[i] = Integer.parseInt(br.read..
2023.07.28
no image
[Java] 레코드, 롬복(lombok)
이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 레코드(record) 데이터 전달을 위한 DTO(Data Transfer Object)를 작성할 때 반복적으로 사용되는 코드를 줄이기 위함 Java 14부터 레코드가 도입되었다. 필드는 읽기만 가능하도록 private final로 선언됨 필드가 읽기만 가능하므로 setter가 없고, getter 이름이 단순히 필드 이름이다. 동등 비교를 위해 hashCode()와 equals() 메소드가 재정의 되어있다. toString()메소드가 재정의 된다. public record Member(String id, String name, int age) { } 이렇게 단순하게 클래스명 앞에 rec..
2023.07.28
no image
[Java] 백준 14단계 - 7785번 문제 (회사에 있는 사람)
문제설명 소스코드 import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); HashMap m = new HashMap(); for (int i = 0; i < N; i++) { String name = sc.next(); String log = sc.next(); if (m.containsKey(name)) m.remove(name); //최초 입력이 아니..
2023.07.27
no image
[Java] 백준 15단계 - 1620번 문제 (나는야 포켓몬 마스터 이다솜)
문제설명 소스코드 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; public class Main { public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); int..
2023.07.27

문제설명

 

 

소스코드

import java.util.Scanner;
public class Main {
    public static void main(String[] args) throws Exception{
    	Scanner sc = new Scanner(System.in);
    	int N = sc.nextInt();
    	long count = 1;
    	if (N==0) System.out.print(1);
    	else
    	{
    		for(int i = 1; i <= N; ++i) count *= i;
        	System.out.print(count);
    	}
    }
}

 

설명

  • 이 문제의 N의 최대값은 12이므로 count의 타입을 long이 아닌 int로 해도 상관없다.

문제설명

 

소스코드

import java.util.Scanner;
public class Main {
    public static void main(String[] args) throws Exception{
    	Scanner sc = new Scanner(System.in);
    	int N = sc.nextInt();
    	System.out.print((int)Math.pow(2, N));
    }
}

 

설명

  • 한 층을 내려올 때마다 경우의 수는 2가지 이므로 N층을 내려올 때 경우의 수는 2^N개 이다.

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


String은 내부 문자열을 수정할 수 없다.

아래의 코드를 보면 다른 문자열을 결합해서 내부 문자열을 변경하는 것처럼 보이지만 사실 'ABCDEF'라는 새로운 String 객체를 생성하는 것이다. 그리고 data 변수는 새로 생성된 String 객체를 참조하게 된다.

String data = "ABC";
data += "DEF";

문자열의 + 연산은 새로운 String 객체가 생성되고 이전 객체는 계속 버려지는 것이기에 효율이 좋지 못하다.

잦은 문자열 변경 작업을 해야 한다면 String 보다는 StringBuilder를 사용하는 것이 좋다.

 

StringBuilder 클래스

StringBuilder는 내부 버퍼에 문자열을 저장해두고 그 안에서 추가, 수정, 삭제 작업을 하도록 설계되어 있다.

따라서 String처럼 새로운 객체를 만들지 않고도 문자열을 조작할 수 있다.

리턴 타입 메소드(매개변수) 설명
StringBuilder append(문자열) 문자열을 끝에 추가
StringBuilder insert(위치, 문자열) 문자열을 지정 위치에 추가
StringBuilder delete(시작 위치, 끝 위치) 시작 위치 ~ 끝 위치 -1를 삭제
StringBuilder replace(시작 위치, 끝 위치, 문자열) 문자열 일부를 대체
StringBuilder reverse() 문자열 전체를 뒤집음
String toString() 완성된 문자열을 리턴

 

StringBuilder의 객체 생성은 아래와 같이한다.

StringBuilder sb =  new StringBuilder();

 

toString()을 제외한 다른 메소드는 StringBuilder를 다시 리턴하기 때문에 연이어서 다른 메소드를 호출할 수 있는 메소드 체이닝 패턴을 사용할 수 있다.

따라서 문자열로 리턴하고 싶다면 toString() 메소드를 호출하면 된다.

자바 프로그램의 실행시간을 단축시키고 싶다면
System.out.println()보다 아래의 방법을 이용하는 것이 빠르다.
StringBuilder sb = new StringBuilder();
sb.append("출력할 내용\n");​

 

하지만 위 방법보다 아래의 방법이 더 빠르다.
sb.append("출력할 내용").append('\n');​

 

public class StringBuilderExample {
	public static void main(String[] args) {
		String data = new StringBuilder()
				.append("DEF")
				.insert(0, "ABC")
				.delete(3, 4)
				.toString();
		System.out.println(data);
	}
}
/*
ABCEF
*/

 


 

StringTokenizer 클래스

문자열이 구분자로 연결되어 있을 경우, 구분자를 기준으로 문자열을 분리하려면 String의 split() 메소드를 이용하거나 java.util 패키지의 StringTokenizer 클래스를 사용할 수 있다.

 

문자열에서 &, 쉼표 , 하이픈 등으로 정규 표현식으로 구분된 문자열을 뽑아낼 경우, 정규 표현식으로 분리하는 split() 메소드를 사용해야한다.

 

그러나 여러 종류가 아닌 한 종류의 구분자가 있다면 StringTokenizer를 사용할 수도 있다.

String data = "홍길동/이수홍/박연수";
StringTokenizer st = new StringTokenizer(data, "/");

 

매개값을 문자열 하나만 넘기면, 구분자를 지정하지 않았으므로 스페이스, 탭, 줄바꿈, 캐리지 리턴 등 기본 구분자가 적용된다.

 

리턴 타입 메소드 설명
int CountTokens() 분리할 수 있는 문자열의 총 개수
boolean hasMoreTokens() 남아 있는 문자열이 있는지 여부
String nextToken() 문자열을 하나씩 가져옴
  • CountTokens() : 문자열이 몇개로 분리되었는지 리턴
  • nextToken() : 분리된 문자열을 하나씩 가져옴
  • hasMoreTokens() : 더 가져올 문자열이 있는지 true or false로 리턴
import java.util.StringTokenizer;

public class StringTokenizerExample {
	public static void main(String[] args) {
		String data1 = "홍길동&이수홍,박연수";
		String[] arr = data1.split("&|,");
		for(String token : arr) {
			System.out.println(token);
		}
		System.out.println();

		String data2 = "홍길동/이수홍/박연수";
		StringTokenizer st = new StringTokenizer(data2, "/");
		while (st.hasMoreTokens()) {
			String token = st.nextToken();
			System.out.println(token);
		}
	}
}
/*
홍길동
이수홍
박연수

홍길동
이수홍
박연수
*/

'Java Category > Java' 카테고리의 다른 글

[Java] 제네릭(Generic)  (0) 2023.07.31
[Java] 랜덤 숫자(난수) 얻기  (0) 2023.07.30
[Java] 레코드, 롬복(lombok)  (0) 2023.07.28
[JAVA] API Document  (0) 2023.07.27
[JAVA] 사용자 정의 예외  (0) 2023.07.26

문제설명

 

소스코드

import java.util.Scanner;
public class Main {
    public static void main(String[] args) throws Exception{
    	Scanner sc = new Scanner(System.in);
    	int N = sc.nextInt();
    	System.out.print(N * (N - 1));
    }
}

 

설명

  • 생략

문제설명

 

소스코드

import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
    public static void main(String[] args) throws Exception{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int arr[] = new int[N]; //가로수의 개수 입력 받음
        int minDivisor = 0;
        int sum = 0;
        for(int i = 0; i < N; ++i) arr[i] = Integer.parseInt(br.readLine()); //가로수의 위치를 입력받음
        for(int i = 1; i < N; ++i) 
        { 
        	int dis = arr[i] - arr[i-1]; //가로수의 거리 차이
        	minDivisor = gcd(dis, minDivisor); // 두 가로수의 최대공약수를 저장
        }
        for(int i = 1; i < N; ++i) sum += ((arr[i] - arr[i-1]) / minDivisor) -1; //'(두 가로수의 거리 / 최대공약수) -1' 를 더함
        System.out.println(sum);
    }
    static int gcd(int a, int b) //유클리드 호제법
    {
    	if(b==0) return a;
    	else return gcd(b,a%b);
    }
}

 

설명

  • 모든 가로수들 중의 최대공약수를 구한다.
  • '(두 가로수의 거리 / 최대공약수) -1' 를 모두 더한뒤 출력하면 된다.

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


레코드(record)

  • 데이터 전달을 위한 DTO(Data Transfer Object)를 작성할 때 반복적으로 사용되는 코드를 줄이기 위함
  • Java 14부터 레코드가 도입되었다.
  • 필드는 읽기만 가능하도록 private final로 선언됨
  • 필드가 읽기만 가능하므로 setter가 없고, getter 이름이 단순히 필드 이름이다.
  • 동등 비교를 위해 hashCode()와 equals() 메소드가 재정의 되어있다.
  • toString()메소드가 재정의 된다.

 

public record Member(String id, String name, int age) {
}

이렇게 단순하게 클래스명 앞에 recode 만 붙이고 뒤에 사용할 필드들을 나열한다.

그러면 자동으로 각 필드와 getter가 생성되고 hashCode(), equals(), toString() 메소드가 자동으로 오버라이딩되어 생성된다.

 

Main.java

public class Main {
	public static void main(String[] args) {
		Member m = new Member("winter", "눈송이", 25);
		System.out.println(m.id());
		System.out.println(m.name());
		System.out.println(m.age());
		System.out.println(m.toString());
		System.out.println();
		
		Member m1 = new Member("winter", "눈송이", 25);
		Member m2 = new Member("winter", "눈송이", 25);
		System.out.println("m1.hashCode(): " + m1.hashCode());
		System.out.println("m2.hashCode(): " + m2.hashCode());
		System.out.println("m1.equals(m2): " + m1.equals(m2) );
	}
}
/*
winter
눈송이
25
Member[id=winter, name=눈송이, age=25]

m1.hashCode(): 306065155
m2.hashCode(): 306065155
m1.equals(m2): true
*/

 

 


 

롬복(lombok)

  • 롬복은 JDK에 포함된 표준 라이브러리는 아니지만 개발자들이 즐겨 쓰는 자동 코드 생성라이브러리이다.
  • 롬복은 레코드와 비슷하지만 더욱 편리한 기능을 제공한다.
  • 레코드와 큰 차이점은 필드가 final이 아니며, 값을 읽는 getter와 setter의 이름이 각 getXxx(또는 isXxx), setXxx로 생성된다.

 

롬복 설치

https://projectlombok.org/download

 

Download

 

projectlombok.org

 

다운받고 cmd를 통해 다운로드한 경로로 이동하고 아래의 명령어를 입력하면 된다.

당연히 다운로드 경로는 사용자마다 다르다.

 

 

설치된 IDE가 나오는데 롬복 라이브러리를 인식하게 할 IDE를 골라준다.

Install / Update 버튼을 누르면 설치가 되고 완료되면 닫아준다.

 

롬복 사용해보기

원하는 프로젝트에 다운로드한 롬복 JAR을 추가해 준다.

 

그리고 Build Path를 설정해 준다.

 

 

이제 아래와 같이 코드를 작성하면

import lombok.Data;
@Data
public class Member {
	private String id;
	private String name;
	private int age;
}

 

아웃라인에 자동으로 메소드들이 선언되어 있는 것을 볼 수 있다.

 

@Data 외에도 아래와 같은 어노테이션을 사용할 수 있다.

출처 : 이것이 자바다 유튜브 동영상 강의

tip
@Data에 포함되어 있는 @RequiredArgsConstructor는 기본적으로 매개변수가 없는 생성자를 포함시키지만, final 또는 @NonNull이 붙은 필드가 있다면 이 필드만 초기화시키는 생성자를 포함시킨다.
출처 : 이것이 자바다 유튜브 동영상 강의
final과 @NonNull의 차이점은 초기화된 final 필드는 변경할 수 없지만(setter가 만들어지지 않음), @NonNull은 null이 아닌 다른 값으로 setter를 통해 변경할 수 있다는 것이다.

문제설명

 

소스코드

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		HashMap<String, String> m = new HashMap<String, String>();
		for (int i = 0; i < N; i++) 
		{
			String name = sc.next();
			String log = sc.next();
			if (m.containsKey(name)) m.remove(name); //최초 입력이 아니면 나간거
			else m.put(name, log); //최초 입력이면 들어온거
		}
		ArrayList<String> list = new ArrayList<String>(m.keySet()); //Hash맵의 Key들을 ArrayList로 변경
		Collections.sort(list, Collections.reverseOrder()); //내림차순으로 정렬
		for(int i = 0; i < list.size(); ++i) System.out.println(list.get(i));
	}
}

 

설명

  1. 이름과 출입 기록을 받는다.
  2. 해당 이름이 해시맵에 없으면 해시맵에 이름과 출입 기록을 추가한다.
    해당 이름이 해시맵에 있으면 해시맵에서 해당 이름과 출입 기록을 삭제한다.(최초 입력이 아니면 나간것이기 때문)
  3. 해시맵의 key들만 ArrayList로 가져온다.
  4. ArrayList를 내림차순으로 정렬한다.
  5. 정렬된 ArrayList를 순차적으로 출력한다.

문제설명

 

 

소스코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int N = Integer.parseInt(st.nextToken());
		int M = Integer.parseInt(st.nextToken());
		StringBuilder sb = new StringBuilder();
		Map<String, Integer> m = new HashMap<>();
		String nameArr[] = new String[N + 1];
		for(int i = 1; i <= N; ++i)
		{
			String name = br.readLine();
			m.put(name,i);
			nameArr[i] = name;
		}
		for(int i = 0; i < M; ++i)
		{
			String input = br.readLine();
			try //일단 input을 int타입으로 변환 시도
			{
				int number = Integer.parseInt(input);
				//변환 성공시
				sb.append(nameArr[number]);
			}catch(Exception e){ //변환 실패시
				sb.append(m.get(input));
			}
			sb.append("\n");
		}
		System.out.println(sb.toString());
	}
}

 

설명

  1. 해시맵과 포켓몬 이름을 저장할 String타입 배열을 선언한다.
    String 타입 배열은 인덱스가 1부터 시작하므로 N+1개를 할당해야한다.
  2. 포켓몬 이름을 입력받아 해시맵과 배열에 저장한다.
  3. try-catch문으로 검색을 문자로할지 숫자로 할지 정한다.
  4. 입력을 int형으로 변환할 수 있으면 배열에서 해당 포켓몬 인덱스를 StringBuilder 버퍼에 저장한다.
    입력을 int형으로 변환할 수 없으면 해시맵에서 해당 포켓몬 이름을 StringBuilder 버퍼에 저장한다.
  5. 저장된 StringBuilder 버퍼를 출력한다.