- 이제 자바(JAVA) 공부의 절반까지 왔다!
문자열 클래스는 암기해야 할 것들이 대부분인데
문자열을 파싱하는데 굉장히 중요한 내용이다.
그럼 다시 힘차게 시작해본다.
- 자바는 문자열을 사용할 때 String 클래스를 사용한다
char(문자) : 작은 따옴표를 사용하며 ‘A’, ‘가', ‘0’ … 이렇게 하나씩...
String(문자열) : 큰 따옴표를 사용하며
"A", "가", "0", "홍길동", "안녕하세요 ?" ... 이런식...
- String 객체 생성은 다음과 같다
String str1 = new String(“홍길동”); // new는 새로운 객체를 생성을 의미한다.
String str2 = “전우치”;
둘 다 객체(인스턴스) 생성하는 방법이며
str1 ,str2는 참조값(주소값)이 생성되며 "홍길동" "전우치"는 힙 영역에 저장된다.
ex) str1이라는 주소를 찾아가니 "홍길동"이라는 문자가 있네?
그러면, 아래를 한번 살펴보자
String str1 = new String("누구인가?");
String str2 = new String("누구인가?");
str1 == str2는 true일까? ( str1와 str2가 같을까? )
ㄴ 정답은 false이다.(다르다)
- Str1과 Str2는 내용이 같더라도 new이기 때문에 다른 공간을 만든다.
Str1은 id=20이라는 주소값(참조값)
Str2는 id=26이라는 주소값(참조값)이 생성된다.
Str3과 Str4는 기존에 있는 값을 사용한다.
이처럼 String은 == 비교 연산자를 통해 내용을 비교할 수 없다.
그러므로 String은 String 관련된 메소드를 사용해야만 내용을 비교할 수 있다.
다음 step에서 방법이 밝혀진다..
- 여기부터는 String을 다루는데 굉장히 유용하면서도 중요한 암기이다.
암기를 하더라도 이해를 하면서 암기를 하면 더 효율적으로 자기화 시킬 수 있을 것이다.
equals() : 문자열의 내용을 비교하는 메소드이다.
ㄴ"내용이 단순히 완전히 똑같은가"를 비교할때 사용한다.
ㄴ일부만 같은 것을 비교하는 거라면 쓸 수 없다.
ㄴ완전히 100% 일치함을 비교할 때 많이 사용한다.
compareTo() : 숫자를 비교한다면 크다(1), 같다(0), 작다(-1)로 반환하지만
문자열의 비교 같은 경우는 같다(0), 그 외는 양수/음수값으로 반환해준다.
예시: 숫자)
Integer x = 3;
Integer y = 4;
System.out.println( x.compareTo(y) );
//x가 y보다 더 큰가? - 작으므로 -1이 출력된다.
예시: (문자열)
String str = "abcd";
// 1) 비교대상에 문자열이 포함되어있을 경우!
// ★ 서로의 문자열 길이의 차이값을 반환해준다.
System.out.println( str.compareTo("abcd") ); // 4-4 = 0 출력
System.out.println( str.compareTo("ab") ); // 4-2 = 2 출력
System.out.println( str.compareTo("a") ); // 4-1 = 3 출력
System.out.println( str.compareTo("c") ); // 97-99= -2 출력??
/*
★ comparTo는 같은 위치의 문자만 비교하기 때문에,
첫번째 문자(a)부터 순서대로 비교해서 다를 경우 바로 아스키값을 기준으로
비교처리를 한다.
아스키코드 : a = 97 / c = 99
*/
"abhg".compareTo("h"); // a = 97, h = 104 이므로 97-104 = -7
"abcd".compareTo("abfd");
// 비교가 불가능한 시점 c와 f를 비교한다.
c = 99, f =102이므로 99-102 = -3
// 2) 비교대상과 전혀 다른 문자열인 경우
ㄴ비교가 불가능한 지점의 문자열 아스키값을 기준
System.out.println( str.compareTo("zefd") ); // -25
// a = 97 / z = 122 이기 때문에 차이값인 -25
System.out.println( str.compareTo("ABCD") ); // 32
// a = 97 / A = 65 이므로 차이값인 32
int[] lengthT1 = new int[5];
System.out.println( lengthT1.length ); // 5 출력 : 배열의 길이
String lengthT2 = "WOW-GOOD";
System.out.println( lengthT2.length() ); // 8 출력 : 문자열 길이
ArrayList<Object> st = new ArrayList<Object>();
System.out.println( st .size() ); // 0 출력 : 리스트 길이
- 단, 기본자료형과의 연산은 아래 사진처럼 사용한다.
String startOne = "Hello world";
System.out.println( startOne.indexOf("l") );
// 0,1,인덱스[2]번째이므로 2가 출력된다.
System.out.println( startOne.indexOf("z") );
// 없으므로 -1이 출력된다.
System.out.println( startOne.indexOf("o",5) );
// indexOf( "찾을 특정 문자" , "시작할 위치" )로 지정할 수 있다.
// 인덱스 5번째부터 찾기 시작하여 o를 찾는다면?
// world의 o인 [7]이 출력된다.
String startOne = "Hello world";
System.out.println( startOne.lastIndexOf("l") );
// 뒤에서부터 l를 찾으므로 인덱스 9가 출력된다.
System.out.println( startOne.lastIndexOf("z") );
// 뒤에서 찾아도 없으므로 -1이 출력된다.
System.out.println( startOne.lastIndexOf("o",5) );
// 인덱스 5번째(공백)을 시작으로 뒤에서부터 찾으므로
// Hello의 o인 인덱스 4가 출력된다.
String str1 = "재미있는 자바 공부";
System.out.println( str1.substring(5) );
// 인덱스 5번째부터 끝까지 출력하라!이므로 '자바 공부'가 출력된다.
System.out.println( str1.substring(0,2) );
// 인덱스 0번째부터 (인덱스 2가 되기전까지) 출력하라!이므로 '재미'가 출력된다.
String str = "chatGPT";
System.out.println( str.charAt(5) );
// 인덱스 5번째인 P가 출력된다.
String.valueOf( ): 괄호 안에 있는 것이 무엇이든 문자열로 바꾸는 메소드이다.
contains(): 대상 문자열에 특정 문자열이 포함되어 있는지 확인하는 메소드
ㄴ대소문자를 구분한다.
String str = "hello my name is...";
System.out.println( str.contains("Hello") );
// 대소문자를 구분하므로 H는 없기에 false 출력
System.out.println( str.contains(" hello") );
// 앞에 공백도 구분하기에 false 출력
System.out.println( str.contains("my name") );
// 일치하기에 true 출력
String study = "자바 공부 재밌다";
System.out.println( study.startsWith("자바") ); // true
System.out.println( study.startsWith("자") );// true
System.out.println( study.startsWith(" 자") );
// 앞에 공백도 취급하므로 false가 출력된다.
String study = "자바 공부 재밌다";
System.out.println( study.endsWith("재밌다 ") );
// 뒤에 공백이 없으므로 false가 출력된다.
System.out.println( study.endsWith("재밌다") );
// 일치하므로 true가 출력된다.
System.out.println( study.endsWith("다") );
// 역시 일치하므로 true가 출력된다.
System.out.println( study.endsWith("밌") );
// 밌으로 끝나지 않으므로 false가 출력된다.
isEmpty() : 문자열의 길이가 0이면 true를 반환
ㄴJAVA 6 이후에 추가된 메소드
isBlank() : 문자열이 비어 있거나, 빈 공백으로만 이루어져 있으면, true를 반환
ㄴJAVA 11 이후에 추가된 메소드
System.out.println("".isEmpty() + "," + "".isBlank()); // true, true
System.out.println(" ".isEmpty() + "," + " ".isBlank()); // false, true
toLowerCase() : 문자열을 모두 소문자로 변환하는 메소드
toUpperCase() : 문자열을 모두 대문자로 변환하는 메소드
trim() : 문자열 맨 앞 맨 뒤에 있는 공백만 제거한 후 반환
codePointAt() : 문자열에서 해당 index의 아스키코드(유니코드)를 반환한다.
String alpa = "abcde";
System.out.println(alpa.codePointAt(2));
// c의 아스키코드가 99이므로 99가 출력된다.
String rt = "우리의 믿음 우리의 사랑 그 영원한";
System.out.println( rt.replace("믿음","축복") );
// "우리의 축복 우리의 사랑 그 영원한" 이 출력된다.
String rt2 = "agdfk;aababbbbaaaaab";
System.out.println( rt2.replace("ab","*") );
// ab가 정확히 일치해야 바꾼다. => agdfk;a**bbbaaaa*
String rt2 = "agdfk;aababbbbaaaaab";
System.out.println( allTest.replaceAll("[ab]","*") );
// a나 b가 포함되면 무조건 다 별로 바꿔버린다 => *gdfk;**************
[replaceAll을 이용한 전체 공백 제거하기]
String hellostr = " 안 녕 하 세 요 반 갑습니 당 ";
// ("\\p{Z}","") 스페이스바를 "" 없애라는 뜻이다.
String changeStr = hellostr.replaceAll("\\p{Z}","");
System.out.println(changeStr);
// 전체 공백이 제거되어 => 안녕하세요반갑습니당 출력!
String rt3 = "사랑 사랑 사랑 사랑 사랑이야~";
System.out.println( rt3.replaceFirst("사랑","믿음") );
// "믿음 사랑 사랑 사랑 사랑이야~" 가 출력된다.
1. [단순한 기준으로 자르기]
String str1 = "hello my name";
// 공백을 기준으로 문자열을 자른다.
String[] spt = str1.split(" ");
System.out.println( spt[0] ); // hello
System.out.println( spt[1] ); // my
System.out.println( spt[2] ); // name
2. [한정된 배열의 크기 안에서 기준을 잡아 자르기]
String str2 = "hello my name";
// 공백을 기준으로 문자열을 자르되 2묶음으로 나눈다.
String[] spt = str2.split(" " , 2);
System.out.println( spt[0] ); // hello
System.out.println( spt[1] ); // my name
3. [메타 문자 기준으로 자르기]
String str3 = "hello.my.name";
String[] spt = str3.split(".");
System.out.println( spt[0] ); // 에러 발생!
System.out.println( spt[1] ); // 에러 발생!
- 3번은 왜 아무것도 출력이 안되는 걸까?
ㄴ바로 자바에서 .은 다른 의미가 있기 때문이다. - 이를 메타 문자라고 한다
ㄴ ^ $ . ? + * |
ㄴ해당 문자를 기준으로 split()을 사용한다면 이스케이프 처리를 해주어야 한다.
ㄴ바로 \\ (역슬래쉬 두번) 을 앞에 입력해주면 된다.
String str4 = "hello.my.name";
// .를 기준으로 잘라 2묶음으로 나눈다
String[] spt = str4.split("\\.",2);
System.out.println( spt[0] ); // hello
System.out.println( spt[1] ); // my.name
String callT = "WoWGood";
callT.equals("woWGood"); // false 반환
callT.equalsIgnoreCase("woWgood"); // true 반환
compareToIgnoreCase() : 대소문자를 무시하고 비교해주는 메소드
String str = "abcd";
System.out.println( str.compareToIgnoreCase("ABCD") ); // 0
System.out.println( str.compareToIgnoreCase("abCD") ); // 0
String.format() : 문자열 형식을 지정하는 메소드
ㄴ 출력 형식을 지정하여 문자열로 반환하고 싶을 때
ㄴ 주로 웹어플리케이션 제작에서 자주 사용된다.
String str = "hellomynameis";
String result = String.format("%s, %S", str, str);
System.out.println(result);
// hellomynameis, HELLOMYNAMEIS
String: 문자열 연산이 적고 멀티쓰레드 환경일 경우
StringBuffer: 문자열 연산이 많고 멀티쓰레드 환경일 경우
StringBuilder: 문자열 연산이 많고 단일쓰레드이거나 동기화를 고려하지 않아도 되는 경우
문자열의 추가,수정,삭제가 빈번하게 발생할 경우라면 String 클래스가 아닌
StringBuffer/StringBuilder를 사용해야 한다.
- String은 문자열을 수정, 추가할때마다 메모리 공간을 매번 새로 만들어서
추가하기 때문에 메모리 낭비가 많을 수 있다.
- StringBuffer/StringBuilder는 문자열을 수정, 추가하더라도 같은 메모리 안에서
문자열을 추가하고 수정하기에 메모리 낭비가 발생하지 않는다.
- StringTokenizer(): 문자열을 분할하는 클래스이다 .
ㄴ 분할한 문자열을 토큰이라고 한다.
String str = "네이버 >링크 타고 바로가기 :www.naver.com";
StringTokenizer st = new StringTokenizer(str, ">:" );
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
//네이버
//링크 타고 바로가기
//www.naver.com
hasMoreTokens(): 토큰이 있으면 true를 반환합니다.
nextToken(): 토큰을 차례로 가져옵니다.
insert(): 특정 위치의 문자열을 추가할 수 있는 메소드
ㄴ(위치, 문자열) 반환값은 StringBuffer 입니다.
StringBuffer sb = new StringBuffer();
sb.append("Simple is Best");
sb.insert(9, "n't");
// Simple isn't Best 가 출력된다.
StringBuffer sb = new StringBuffer();
sb.append("Simple isn't Best");
sb.delete(9,12); // 인덱스 9번째부터 12가 되기 전까지 문자열이 삭제된다.
// Simple is Best 가 출력된다.
StringBuffer sb = new StringBuffer();
sb.append("Simple is Best");
StringBuffer rsb = sb.reverse();
// tseB si elpmiS 가 출력된다.
- 사용자로부터 입력을 받아 "개" 가 포함되었을 경우
ㄴ "나는 멍멍이"로 출력되는 프로그램을 만드시오- 사용자로부터 입력을 받아 "사실"을 입력할 경우 "(힘들지만 파이팅..)"이
ㄴ 출력되는 프로그램을 만드시오- 주민등록번호 앞자리를 입력받아 "몇년 몇월 몇일에 태어나셨군요~"가
ㄴ 출력되는 프로그램을 만드시오- 사용자로부터 아이디를 입력받은 후 다음 조건에 만족하는지
확인할 수 있는 프로그램을 만드시오
ㄴ아이디는 8~12자 사이로만 사용할 수 있다. (length() 메서드 활용)
ㄴ영문과 숫자로만 입력할 수 있다. (charAt() 메서드 활용)
ㄴ특수기호, 공백, 그 외 모든 문자는 입력할 수 없다.
ㄴ위 조건에 만족하면 true, 만족하지 않으면 false를 반환한다.- 참가자의 이름을 입력받아 끝말잇기 게임을 만드시오
(끝말을 이으면 게임을 이어가고 끝말이 틀리면 패배한다)
입력값이 true false를 결정하기 위해 매개변수가 있는 idView 메소드를 생성후
조건에 걸리면 false로 넘어가버리게 한다.
public class StringID
{
public static void main(String[] args)
{
// 문제1] 파일명 : QuValidateId.java
// 사용자로 부터 아이디를 입력받은 후 다음 조건에 만족하는지 확인할 수 있는 프로그램을 작성하시오.
// 아이디는 8~12자 사이로만 사용할 수 있다. (length() 메서드 활용)
// 영문과 숫자로만 입력할 수 있다. (charAt() 메서드 활용)
// 특수기호, 공백, 그 외 모든 문자는 입력할 수 없다.
// 위 조건에 만족하면 true, 만족하지 않으면 false를 반환한다.S
// 1. 사용자로부터 아이디 입력받고 저장하기
System.out.print("아이디를 입력하세요:");
Scanner scan = new Scanner(System.in);
String id = scan.nextLine();
// 2. 아이디어:
// 3개 이상의 다양한 조건이 있다. 조건을 모두 담아서
// 일치하면 스위치 켜짐(true)로 보내고
// 불일치하면 스위치 꺼짐(false)로 보낸다.
boolean isOk = idView(id); // 메소드명(매개변수)로 생성한다,
if (isOk == true)
{
System.out.println("사용할 수 있는 아이디입니다.");
} else
{
System.out.println("사용할 수 없습니다.");
}
}
// 3. 메소드 생성후 헤깔릴 수 있으니 매개변수(스트링 형태) 변경
static boolean idView(String inputId)
{
// 4. 아래 조건들에 걸리지 않으면 그대로 true로 반환된다.
boolean isOk = true;
// 5. 조건1] 아이디 길이 탐색(8~12)
if (inputId.length() >= 8 && inputId.length() <= 12)
{
// 6. 조건 통과시 다음 조건을 확인하기 위해 반복문
for (int i = 0; i < inputId.length(); i++) // 반복해서 확인한다
{
// 7. 각 문자가 영문 또는 숫자인지 확인한다.
char idchr = inputId.charAt(i);
// System.out.printf("인덱스%d:%c\n", i, idchr); // 디버깅 확인용
// 8. 아이디가 영문 또는 숫자가 아니라면 false로 반환(아스키코드)
if (!((idchr >= '0' && idchr <= '9') || (idchr >= 'a' && idchr <= 'z')
|| (idchr >= 'A' && idchr <= 'Z')))
{
System.out.println(idchr + "=> 사용불가!");
isOk = false;
// 문자열에서 허용되지 않은 문자를 찾으면 뒷 부분은 검사할 필요가 없다
// 즉시 반복문 for를 탈출한다
break;
}
}
}
else
{
// 길이가 잘못되었다면 사용불가 false로 반환
isOk = false;
}
return isOk;
}
}
public class StringGame
{
public static void main(String[] args)
{
/*
5.참가자의 이름을 입력받아 끝말잇기 게임을 만드시오
(끝말을 이으면 게임을 이어가고 끝말이 틀리면 패배한다)
*/
System.out.println("끝말잇기 게임을 시작합니다.");
System.out.println("참가할 인원은 몇명?(숫자만): ");
//1. 입력값을 받고 player라는 변수에 저장한다.
Scanner scan = new Scanner(System.in);
int player = scan.nextInt();
//2. arr 배열에 입력한 변수 player를 넣는다.
String arr[] = new String[player];
//3. 변수 player 명만큼 반복탐색
for(int i=0; i<player; i++)
{
//4. 참가자 데이터 받기
System.out.println("참가자 이름>>");
//5. 문자열 형의 name 변수를 입력받아 arr[i]번째 배열에 차곡차곡 넣기
String name = scan.next();
arr[i] = name;
}
String str = "컴퓨터";
System.out.println("시작 단어는 >> [" + str + "]");
//6. 무한반복: 게임의 틀
while(true)
{
//7. 플레이어의 인원수만큼 반복 탐색
for(int i=0; i<arr.length; i++)
{
int lastsu = str.length()-1; //컴퓨터:끝글자의 위치를 숫자로 저장
char lastchar = str.charAt(lastsu); // 끝글자를 문자로 뽑아냄
//8. 차례를 만들어줌
System.out.println(arr[i] + ">> ");
//9. 여기서부터는 입력할 단어를 받음
String word = scan.next();
//10. 입력값 미달(길이가 1자만 입력하면?)
if(word.length()<2)
{
System.out.println(arr[i]+": 길이가 짧아 패배!");
System.exit(0);
}
//11. 마지막 글자와 입력한 시작 글자가 일치하지 않으면?
if(word.charAt(0) != lastchar)
{
System.out.println(arr[i]+": 끝말을 잇지 못해 패배!");
System.exit(0);
}
//12. 입력 글자도 게임에 적용되기 위해 넣는다.
str=word;
}
}
}
}
- 비록 암기이나 문자열을 파싱하면서 자유롭게 다루는데 굉장히 중요한
String 클래스가 끝이 났다. 다음 포스팅은
역시 매우 중요한 상속에 대해 알아본다!
꿀 떨어지는 포스팅은 앞으로도 계속