String클래스
- 문자열을 다루기 위한 클래스
- String클래스 = 데이터(char[])(문자배열) + 메서드(문자열 관련)
- 인스턴스 생성시 생성자의 매개변수로 입력 받는 문자열은 문자형 배열(char[])로 저장되는 것
String클래스의 구조
-> String클래스는 앞에 final이 붙어 있으므로 다른 클래스의 조상이 될 수 없다.
내용을 변경할 수 없는 불변(immutable) 클래스
String a = “a”;
String b = “b”;
ab = a + b;
- 덧셈 연산자(+)를 이용한 문자열 결합은 성능이 떨어짐(매 연산 시 마다 새로운 문자열 객체가 만들어져서 메모리 공간을 차지해서)
- 문자열의 결합이나 변경이 잦다면, 내용을 변경가능한 StringBuffer(내용변경가능)를 사용
문자열의 비교
(1) 문자열 리터럴을 지정하는 방법 String str = “abc”;
(2) String클래스의 생성자를 사용해서 만드는 방법 String str = new String(“abc”);
- 문자열 리터럴로 문자열을 만들면 기존의 것을 재사용하기 때문에 하나의 문자열을 여러 참조변수가 공유함
- new 연산자에 의해서 항상 새로운 String 인스턴스가 생성(새로운 문자열이 만들어짐)
str1 == str2 ? true | str3 == str4 ? false |
str1.equals(str2) ? true | str3.equals(str4) ? true |
equlas는 내용 비교 => true가 나옴, 대입연산자는 주소 비교 => true가 나올 수도 있고, false가 나올 수도 있다. |
문자열 리터럴
- 문자열 리터럴(상수)은 프로그램 실행 시 자동으로 생성된다.(constant poo(상수저장소)에 저장)
-> “AAA”를 담고 있는 String인스턴스가 하나 생성된 후. 참조변수 s1, s2, s3는 모두 이 String 인스턴스 참조
- 자동으로 만들어진 “AAA” 객체에 각 참조변수가 공유함
- 같은 내용의 문자열 리터럴은 하나만 만들어진다.
- 내용이 변경 불가해서 여러 참조변수가 하나의 String 객체를 공유해도 문제가 없음
빈 문자열(“ “, empty string)
- 내용이 없는 문자열, 크기가 0인 char형 배열을 저장하는 문자열
- String str = “”; // str을 빈 문자열로 초기화
크기가 0인 배열을 생성하는 것은 어느 타입이나 가능
char[ ] chArr = new char[0]; // 길이가 0이고 참조변수가 chArr인 char배열
int[ ] iArr = { }; // 길이가 0이고 참조변수가 iArr인 int 배열
배열의 크기가 [10]이면 int는 4byte, 4byte x 10(길이, length) = 40 byte(크기, size)
-> 하지만 자바에서는 혼용해서 쓰고 있음(자바에서 메모리를 다루지 않아서) 40byte로 쓰지 않고 주로 10을 씀!(크기나 배열이나 자바에서는..)
문자(char)와 문자열(String)의 초기화
String s = “”; // 빈 문자열로 초기화
char c = ‘ ‘; // 공백으로 초기화
- 왼쪽 코드처럼 작성하기!
- 왼쪽 코드는 빈 객체가 하나가 만들어져서 str1, str2, str3이 공유하면서 메모리를 적게 사용할 수 있는데 오른쪽 코드는 new 연산자를 써서 빈 객체가 세 개가 만들어짐
String클래스의 생성자와 메서드
메서드/설명 | 예제 | 결과 |
String(String s) (잘 사용하지 않음) | String s = new String(“Hello”); | s = “Hello” |
주어진 문자열(s)를 갖는 String인스턴스를 생성한다. | ||
String(char[ ] value) | char[ ] c = {‘H’, ’e’, ’l’, ’l’, ’o’}; String s = new String(c) |
s = “Hello” |
주어진 문자열(value)을 갖는 String인스턴스를 생성한다.( char[ ] -> String, 반대로는 String -> toCharArray( )) | ||
String(StringBuffer buf) | StringBuffer sb = new StringBuffer(“Hello”); String s = new String(sb); |
s = “Hello” |
Stringbuffer인스턴스가 갖고 있는 문자열과 같은 내용의 String인스턴스를 생성한다. (Stringbuffer는 내용변경가능) | ||
char charAt(int index) | String s = “Hello”; String n = “0123456”; char c = s.charAt(1); char c2 = n.charAt(1); |
c = ‘e’ c2 = ‘1’ |
지정된 위치(index)에 있는 문자를 알려준다.(index는 0부터 시작) | ||
int compareTo(String str) | int i = “aaa”.compareTo(“aaa”); int i2 = “aaa”.compareTo(“bbb”); int i3 = “bbb.”.compareTo(“aaa”); 사전대로면 음수 사전반대면 양수 |
i=0 같으면 i2 = -1(오른쪽이 크면 음수) i3 = 1(오른쪽이 작으면 양수) |
문자열(str)과 사전순서로 비교한다. 같으면 0을 사전순으로 이전이면 음수를, 이후면 양수를 반환한다.(정렬할 때 사용) | ||
String concat(String str) | String s = “Hello”; String s2 = s.concat(“World”) |
s2 = “Hello World” |
문자열(str)을 뒤에 덧붙인다. | ||
boolean contains(CharSequence s) | String s = “abcdefg”; Boolean b = s.contains(“bc”) |
b = true |
지정된 문자열(s)이 포함되었는지 검사 (CharSequence는 인터페이스) | ||
boolean endsWith(String suffix) | String file = “Hello.txt”; Boolean b = file.endsWith(“txt”); |
b = true |
지정된 문자열(suffix)로 끝나는지 검사<-> startswith | ||
Boolean equals(Object obj) | String s = “Hello”; Boolean b = s.equals(“Hello”); Boolean b2 = s.euqals(“hello”); |
b = true b2 = true |
매개변수로 받은 문자열(obj)과 String인스턴스의 문자열을 비교한다. obj가 String이 아니거나 문자열이 다르면 falst 반환 | ||
Boolean equalsIgnoreCase(String str) | String s = “Hello”; boolean b = s.equalsIgnoreCase(“HELLO”); boolean b2 = s.equalsIgnoreCase(“heLLO”); |
b = true b2 = true |
문자열과 String인스턴스의 문자열을 대소문자 구분없이 비교(대소문자 무시) | ||
int indexof(int ch) | String s = “Hello”; int idx1 = s.indexOf(‘o’); int idx2 = s.indexOf(‘k’); |
idx1 = 4 idx2 = -1 |
주어진 문자(ch)가 문자열에 존재하는지 확인해 위치(index)를 알려준다. 못 찾으면 -1을 반환한다.(index 0부터 시작) | ||
int indexOf(int ch, int pos) | String s = “Hello”; int idx1 = s.indexOf(‘e’, 0); int idx2 = s.indexOf(‘e’, 2); |
idx = 1 idx2 = -1 |
주어진 문자(ch)가 문자열에 존재하는지 지정된 위치(pos)부터 확인해 위치(index)를 알려준다. 못 찾으면 -1을 반환한다. | ||
int indexOf(String str) | String s = “ABCDEFG”; int idx = s.indexOf(“CD”); |
idx = 2 |
주어진 문자열이 존재하는지 확인해 그 위치(index)를 알려준다. 없으면 -1을 반환한다. | ||
int lastIndexOf(int ch) | String s = “java.lang.Object”; int idx1 = s.lastIndexOf(‘.’); int idx2 = s.indexOf(‘.’); |
idx1 = 9 idx2 = 4 |
지정된 문자 또는 문자코드를 문자열의 오른쪽 끝에서부터 찾아서 위치(index)를 알려준다. 못 찾으면 -1을 반환한다. | ||
int lastIndexOf(String str) | String s = “java.lang.Object”; int idx1 = s.lastIndexOf(“java”); int idx2 = s.indexOf(“java”); |
idx1 = 10 idx2 = 0 |
지정된 문자열을 인스턴스의 문자열문자열부터 찾아서 위치(index)를 알려준다. 못 찾으면 -1 반환 | ||
int length( ) | String s = “Hello”; int length = s.length |
length = 5 |
문자열의 길이를 반환 | ||
String[ ] split(String regex) | String animals = “dog, cat, bear”; String[ ] arr = animals.split(“,”); |
arr[0] = “dog” arr[1] = “cat” arr[2] = “bear” |
문자열을 지정된 분리자(regex)로 나누어 문자열 배열에 담아 반환 | ||
String[ ] split(String regex, int limit) | String animals = “dog, cat, bear”; String[ ] arr = animals.split(“,”,2); (두 부분으로 나눈다!) |
arr[0] = “dog” arr[1] = “cat, bear” |
문자열을 지정된 분리자(regex)로 나누어 문자열 배열에 담아 반환. 단 문자열 전체를 지정된 수(limit)로 자른다. | ||
boolean startsWith(String prefix) | String s = “java.lang.Object”; Boolean b = s.startsWith(“java”); boolean b2 = s.startsWith(“lang”); |
b = true b2 = false |
주어진 문자열(prefix)로 시작하는지 검사한다. | ||
String substring(int begin) String substring(int begin, int end) |
String s = “java.lang.object”; String c = s.substring(10); String p = s.substring(5, 9); |
c = “Object” p = “lang” |
주어진 시작위치(begin)부터 끝 위치(end)범위에 포함된 문자열을 얻는다. 이 때 시작위치의 문자는 범위에 포함되지만, 끝 위치의 문자는 포함되지 않음 | ||
String toLowerCase( ) | String s = “Hello”; String s1 = s.toLowerCase( ); |
s1 = “hello” |
String인스턴스에 저장 되어있는 모든 문자열을 소문자로 변환하여 반환 | ||
String toUpperCase( ) | String s = “Hello”; String s1 = s.toUpperCase( ); |
s1 = “HELLO” |
String인스턴스에 저장 되어있는 모든 문자열을 대문자로 변환하여 반환 | ||
String trim( ) | String s = “ Hello World “; String s1 = s.trim( ); |
s1=”Hello World” |
문자열의 왼쪽 끝과 오른쪽 끝에 있는 공백을 없앤 결과를 반환. 이 때 문자열 중간에 있는 공백은 제거되지 않음 | ||
String replace (char old, char nw) | String s = “Hello”; String s1 = s.replace(‘H’, ‘C’); |
s1 = “Cello” |
문자열 중의 문자(old)를 새로운 문자(nw)로 바꾼 문자열을 반환 | ||
static String valueOf(Boolean b) static String valueOf(char c) static String valueOf(int i) static String valueOf(long l) static String valueOf(float f) static String valueOf(double d) static String valueOf(Object o) |
String b = String.valueOf(true); String c = String.valueOf(‘a’); String i = String.valueOf(100); String l = String.valueOf(100L); String f = String.valueOf(10f); String d = String.valueOf(10.0); java.util.Date dd = new java.util.Date( ); String date = String.valueOf(dd) |
b = “true” c = “a” i = “100” l = “100” f = “10.0” d = “10.0” date = “wed Jan 27 21:24:29 KST 2016” |
지정된 값을 문자열로 변환하여 반환한다. 참조변수의 경우, toString( )을 호출한 결과를 반환 |
join( )과 StringJoiner
- join( )은 여러 문자열 사이에 구분자를 넣어서 결합한다.
- 구분자로 문자열을 자르는 split( )과 반대의 작업을 함
String animals = "dog,cat,bear";
String[] arr = animals.split(","); // 문자열을 ','를 구분자로 나눠서 배열에 저장
String str = String.join("-", arr); // 배열의 문자열을 '-'로 구분해서 결합
System.out.println(str); // dog-cat-bear
예제)
import java.util.StringJoiner;
public class StringEx4 {
public static void main(String[] args) {
String animals = "dog,cat,bear";
String[] arr = animals.split(",");
String arrToStr = String.join("-",arr);
System.out.println(arrToStr);
// System.out.println(String.join("-",arr)); 위 코드와 동일
StringJoiner sj = new StringJoiner("/","{","}"); // 첫번재 문자는 문자열 사이에!
for(String s :arr) {
sj.add(s);
}System.out.println(sj.toString());
// for(int i=0;i<arr.length;i++) { // 위 코드와 동일
// sj.add(arr[i]);
// }
// System.out.println(sj);
}
}
문자열과 기본형 간의 변환
1) 숫자(기본형 값))를 문자열(String)로 바꾸는 방법
int i = 100;
String str1 = i + ""; // 100을 '100'으로 변환하는 방법1: 편리
String str2 = String.valueOf(i); // 100을 '100'으로 변환하는 방법2: 빠름
2) 문자열을 숫자로 바꾸는 방법
int i2 = Integer.parseInt("100"); // "100"을 100으로 변환하는 방법1: 옛날
int i3 = Integer.valueOf("100"); // "100"을 100으로 변환하는 방법2: 최근
Integer i4 =Integer.valueOf("100"); // 원래는 반환타입이 Integer(i3와 같은 표현)
i2와 i3은 반환타입이 기본형이라 똑같은데 i4는 반환타입이 Integer라서 약간 다름
예제)
int iVal = 100;
String strVal = String.valueOf(iVal); // int를 String으로 변환
// String strVal = ival + "";
double dVal = 200.0;
String strVal2 = dVal + ""; // double을 String으로 변환
// String strVal2 = String.valueOf(dval);
// 문자열을 숫자로 바꾸는 방법(위 코드와 아래 코드는 같은데 parse를 valueOf로 변형한 것!)
double sum = Integer.parseInt(strVal) + Double.parseDouble(strVal2);
double sum2 = Integer.valueOf(strVal) + Double.valueOf(strVal2);
// 위 코드와 아래 코드는 같음
System.out.println(String.join("",strVal, "+", strVal2, "=")+sum); //구분자 없이 하나로 합치기!
System.out.println(strVal+"+"+strVal2+'='+sum2);
StringBuffer클래스
- 문자열을 저장하고 다루기 위한 클래스
- String처럼 문자형 배열(char[ ])을 내부적으로 가지고 있다.
- StringBuffer인스턴스에 저장될 문자열의 길이를 고려해 충분히 여유있는 크기로 지정하는 것이 좋음
- 버퍼의 크기를 지정해주지 않으면 16개의 문자를 저장할 수 있는 크기의 버퍼를 생성
public StringBuffer(int length) { // 적절한 크기를 length에 저장해주기!
value = new char[length];
shared = false;
}
public StringBuffer() {
this(16); // 버퍼의 크기를 지정하지 않으면 버퍼의 크기는 16이 된다.
}
public StringBuffer(String str) {
this(str.length() + 16); // 지정한 문자열의 길이보다 16이 더 크게 버퍼를 생성
append(str);
}
StringBuffer의 생성자
- 배열은 길이 변경불가. 공간이 부족하면 새로운 배열 생성(보통 기존 배열의 두 배)해야 함
1) 새로운 배열 생성
2) 기존 내용을 복사
3) 참조변수 변경
StringBuffer의 변경
- String과 달리 내용을 변경할 수 있다.(mutable)
StringBuffer sb = new StringBuffer("abc");
sb.append("123"); // sb의 내용 뒤에 "123"을 추가한다.
-> append( )는 지정된 내용을 StringBuffer에 추가 후, StringBuffer의 참조를 반환(반환타입이 StringBuffer)
-> 그 외 delete( ): 삭제, insert( ): 삽입
-> 오른쪽 코드처럼(.append.append)를 쓸 수 있는 이유가 반환타입이 StringBuffer이기 때문!(메서드 체이닝: 메서드를 계속 연결해서 호출할 수 있음)
-> sb도 sb2도 같은 주소를 가리킴
StringBuffer의 비교
- StringBuffer는 equals과 오버라이딩 되어있지 않다. (주소로 비교) -> this == obj
- 반면에 toString( )은 오버라이딩되어 있어서 StringBuffer인스턴스에 toString( )을 호출하면, 담고 있는 문자열 반환
- StringBuffer의 객체를 to.String( )을 사용해서 String으로 변환 후에 equals로 비교해야 한다.
StringBuffer의 생성자와 메서드
- StringBuffer 생성자에 아무것도 넣지 않으면 길이가 16인 배열(char[ ])이 생김
- 만약 10을 넣으면 길이가 10인 배열(char[ ])이 생김
- StringBuffer로 배열을 만든다면 StringBuffer(int length)를 사용!!
- sb, sb2, sb3는 다 같은 배열(char[ ])을 가리키고 있음!(같은 StringBuffer타입 객체를 사용해서)
- StringBuffer는 자기 자신을 반환
- 버퍼크기(char[ ]) 배열의 크기는 100이고 저장된 문자열의 길이는 4이다.
- delete은 문자 n개 제거, deleteCharAt은 문자 1개 제거
예제) StringBuffer의 생성자와 메서드
StringBuffer sb = new StringBuffer("01");
StringBuffer sb2 = sb.append(23);
sb2.append(4).append(56);
StringBuffer sb3 = sb.append(78);
sb3.append(9.0);
System.out.printf("%s ", sb);
System.out.printf("%s ", sb2);
System.out.printf("%s\n", sb3);
System.out.printf("sb:%s ", sb.deleteCharAt(10)); // 10번째숫자 삭제
System.out.printf("sb:%s ", sb.delete(3,6)); // 3번째 숫자부터 5번째 숫자까지 삭제
System.out.printf("sb2:%s ", sb2.insert(3, "abc")); // 3번째 자리부터 순서대로 abc 삽입
System.out.printf("sb3:%s\n", sb3.replace(6,sb.length(),"END")); // 6번째 숫자부터 마지막까지의 숫자를 END로 치환
System.out.printf("capacity:%d ", sb.capacity()); // 배열 객체의 크기
System.out.printf("length:%d", sb.length()); // 배열 객체 안에 저장되어 있는 문자열의 길이
StringBuilder
- StringBuffer와 거의 유사함
- StringBuffer는 동기화 되어 있고, StringBuilder는 동기화 되어있지 않음
(StringBuffer와 StringBuilder는 동기화 여부의 차이)
- 동기화란? 멀티 쓰레드에 안전(thread-safe)한 것 -> 데이터 보호
싱글 쓰레드 | 멀티 쓰레드 |
한 번에 1개만 작업 | 한 번에 여러 개 작업(두가지 작업을 동시에 진행) |
데이터를 공유하면서 에러가 날 수 있는데 이것을 막아주는 것이 동기화! |
- 멀티 쓰레드 프로그램이 아닌 경우, 동기화는 불필요한 성능저하 -> 이 때 StringBuffer대신 StringBuilder를 사용하면 성능 향상(싱글쓰레드 프로그램에는 StringBuilder 사용!)
StringBuffer sb1 = new StringBuffer("abc"); // StringBuffer 사용
sb1.append("def”);
StringBuilder sb1 = new StringBuilder("abc"); // StringBuilder 사용
sb1.append("def");
https://www.codejava.net/java-core/the-java-language/why-use-stringbuffer-and-stringbuilder-in-java
'멀티캠퍼스 풀스택 과정 > Java의 정석' 카테고리의 다른 글
자바의 정석6-4 오토박싱 & 언박싱 (0) | 2022.01.07 |
---|---|
자바의 정석6-3 Math클래스, Rapper클래스, Number클래스 (0) | 2022.01.07 |
자바의 정석6-1 Java.lang패키지, eqauls, hasecode, toString (0) | 2022.01.07 |
자바의 정석5-3 사용자 정의 예외, 예외 되던지기, 연결된 예외 (0) | 2022.01.06 |
자바의 정석5-2 예외 발생, 예외 처리, Finally블럭 (0) | 2022.01.06 |