Java Language
문자열
수색…
소개
문자열 ( java.lang.String
)은 프로그램에 저장된 텍스트 조각입니다. 문자열은 Java에서 원시 데이터 유형 이 아니지만 Java 프로그램에서 매우 일반적입니다.
Java에서 문자열은 변경할 수 없으므로 변경할 수 없습니다. (불변성에 대한 자세한 설명은 여기 를 클릭 하십시오 .)
비고
Java 캐릭터 라인은 불변 이므로, String
를 조작하는 모든 메소드 는 새로운 String
오브젝트를 돌려줍니다 . 원래 String
은 변경하지 않습니다. 여기에는 C 및 C ++ 프로그래머가 대상 String
객체를 변경하려는 substring 및 대체 메소드가 포함됩니다.
컴파일시에 값을 결정할 수없는 두 개 이상의 String
객체를 연결하려면 String
대신 StringBuilder
를 사용하십시오. 이 기법은 StringBuilder
가 변경 가능하기 때문에 새로운 String
객체를 생성하고 연결하는 것보다 더 효율적입니다.
StringBuffer
는 String
객체를 연결하는 데에도 사용할 수 있습니다. 그러나이 클래스는 스레드로부터 안전하도록 설계되어 각 연산 전에 뮤텍스를 가져 오기 때문에 성능이 떨어집니다. 문자열을 연결할 때 스레드 안전성이 거의 필요하지 않으므로 StringBuilder
를 사용하는 것이 가장 좋습니다.
문자열 연결을 단일 표현식으로 표현할 수 있다면 +
연산자를 사용하는 것이 좋습니다. 자바 컴파일러는 +
연결을 포함하는 표현식을 String.concat(...)
또는 StringBuilder
사용하여 효율적인 일련의 연산으로 변환합니다. StringBuilder
명시 적으로 사용하는 방법은 연결에 여러 표현식이 포함될 때만 적용됩니다.
중요한 정보를 문자열에 저장하지 마십시오. 누군가 실행중인 응용 프로그램의 메모리 덤프를 얻을 수 있으면 기존의 모든 String
객체를 찾아 내용을 읽을 수 있습니다. 여기에는 연결할 수없고 가비지 수집을 기다리는 String
객체가 포함됩니다. 이것이 염려되는 경우 민감한 문자열 데이터를 마친 후 바로 삭제해야합니다. String
객체는 변경할 수 없기 때문에이 작업을 수행 할 수 없습니다. 따라서 민감한 문자 데이터를 저장하려면 char[]
객체를 사용하고 작업이 끝나면 닦으십시오 (예 : '\000'
문자로 덮어 쓰는 것이 좋습니다).
모든 String
인스턴스는 문자열 리터럴에 해당하는 인스턴스조차도 힙에 만들어집니다. 문자열 리터럴의 특별한 점은 JVM이 동일 문자 (즉, 같은 문자로 구성된 모든 리터럴)가 단일 String
객체 (이 동작은 JLS에 지정되어 있음)로 표시된다는 것입니다. 이것은 JVM 클래스 로더에 의해 구현됩니다. 클래스 로더는 클래스를로드 할 때 클래스 정의에 사용되는 문자열 리터럴을 검색하고 매번 읽을 때마다이 리터럴의 문자열 풀에 이미 레코드가 있는지 확인합니다 (리터럴을 키로 사용) . 리터럴에 대한 항목이 이미있는 경우 해당 리터럴에 대한 쌍으로 저장된 String
인스턴스에 대한 참조가 사용됩니다. 그렇지 않으면 새 String
인스턴스가 만들어지고 문자열 풀에 리터럴 (키로 사용됨)에 대한 인스턴스에 대한 참조가 저장됩니다. ( 문자열 internation 참조).
문자열 풀은 Java 힙에 보관되며 일반 가비지 수집의 영향을받습니다.
Java 7 이전의 Java 릴리스에서는 "PermGen"으로 알려진 힙의 특수 부분에 문자열 풀이 보관되었습니다. 이 부분은 때때로 수집되었을뿐입니다.
Java 7에서 문자열 풀은 "PermGen"에서 이동되었습니다.
문자열 리터럴은이를 사용하는 모든 메서드에서 암시 적으로 연결할 수 있습니다. 즉, 코드 자체가 가비지 수집 된 경우에만 해당 String
객체를 가비지 수집 할 수 있습니다.
Java 8까지 String
객체는 UTF-16 char 배열 (char 당 2 바이트)로 구현됩니다. Java 9에는 String
을 바이트 배열 (LATIN-1) 또는 문자 (UTF-16)로 인코딩했는지 여부를 나타내는 인코딩 플래그 필드가있는 바이트 배열로 구현하는 제안이 있습니다.
문자열 비교
스트링의 동일성을 비교하려면, String 오브젝트의 equals
또는 equalsIgnoreCase
메소드를 사용할 필요가 있습니다.
예를 들어 다음 스 니펫은 String
의 두 인스턴스가 모든 문자에서 같은지 여부를 결정합니다.
String firstString = "Test123";
String secondString = "Test" + 123;
if (firstString.equals(secondString)) {
// Both Strings have the same content.
}
이 예는 대소 문자에 관계없이 그것들을 비교합니다 :
String firstString = "Test123";
String secondString = "TEST123";
if (firstString.equalsIgnoreCase(secondString)) {
// Both Strings are equal, ignoring the case of the individual characters.
}
참고 equalsIgnoreCase
당신이 지정할 수 없습니다 Locale
. 예를 들어, 영어로 "Taki"
와 "TAKI"
의 두 단어를 비교하면 동등합니다. 그러나 터키에서는 그들은 다릅니다 (터키어에서는 소문자 I
가 ı
). 이와 같은 경우 Locale
을 사용하여 두 문자열을 소문자 (또는 대문자)로 변환 한 다음 equals
비교하는 것이 해결책입니다.
String firstString = "Taki";
String secondString = "TAKI";
System.out.println(firstString.equalsIgnoreCase(secondString)); //prints true
Locale locale = Locale.forLanguageTag("tr-TR");
System.out.println(firstString.toLowerCase(locale).equals(
secondString.toLowerCase(locale))); //prints false
== 연산자를 사용하여 문자열을 비교하지 마십시오.
모든 문자열이 인턴됨을 보장 할 수 없다면 (아래 참조) ==
또는 !=
연산자를 사용하여 문자열을 비교하면 안됩니다 . 이 연산자는 실제로 참조를 테스트하고, 여러 String
객체가 동일한 String을 나타낼 수 있기 때문에 잘못된 대답을하기 쉽습니다.
대신 String.equals(Object)
메서드를 사용하십시오.이 메서드는 해당 값을 기반으로 String 개체를 비교합니다. 자세한 설명은 Pitfall : ==를 사용하여 문자열 비교 를 참조하십시오.
switch 문에서 문자열 비교
자바 1.7에서, switch
문에서 String 변수를 리터럴과 비교할 수 있습니다. String가 null가 아닌지 확인합니다. 그렇지 않으면 항상 NullPointerException
throw됩니다. 값은 String.equals
대소 문자 구별)를 사용하여 비교됩니다.
String stringToSwitch = "A";
switch (stringToSwitch) {
case "a":
System.out.println("a");
break;
case "A":
System.out.println("A"); //the code goes here
break;
case "B":
System.out.println("B");
break;
default:
break;
}
문자열과 상수 값 비교하기
String
과 상수 값을 비교할 때 equals
의 왼쪽에 상수 값을 넣으면 다른 String이 null
경우 NullPointerException
을받지 않도록 할 수 있습니다.
"baz".equals(foo)
foo
가 null
경우, foo.equals("baz")
는 NullPointerException
를 슬로우하지만, "baz".equals(foo)
는 false
됩니다.
보다 읽기 쉬운 대안은 Objects.equals(foo, "baz")
두 매개 변수 모두에 대해 null 검사를 수행하는 Objects.equals()
를 사용하는 것입니다.
( 참고 : 일반적으로 NullPointerExceptions
을 피하는 것이 더 나은지, 아니면 근본 원인을 수정하는 것이 더 나은지에 대해서는 논쟁의 여지가 있습니다 ( 여기 및 여기 참조) 확실히 회피 전략을 "모범 사례"라고 부르는 것은 정당하지 않습니다.
문자열 정렬
String
클래스는 String.compareTo
메서드로 Comparable<String>
을 구현합니다 (이 예제의 시작 부분에서 설명). 이것에 의해 String
객체의 자연 순서 부를 대문자와 소문자의 순서로 지정합니다. String
클래스는 대소 문자를 구분하지 않는 정렬에 적합한 CASE_INSENSITIVE_ORDER
라는 Comparator<String>
상수를 제공합니다.
interned 문자열과 비교하기
Java 언어 사양 ( JLS 3.10. 6 )에서는, 다음과 같이 설명하고 있습니다.
또한 문자열 리터럴은 항상
String
클래스의 동일한 인스턴스를 참조합니다. 이는 문자열 리터럴 또는 더 일반적으로 상수 표현식의 값인 문자열이String.intern
메서드를 사용하여 고유 한 인스턴스를 공유하도록 인턴 되기 때문String.intern
. "
즉, ==
사용하여 두 문자열 리터럴에 대한 참조를 비교하는 것이 안전하다는 의미입니다. 또한 String.intern()
메서드를 사용하여 생성 된 String
객체에 대한 참조도 마찬가지입니다.
예 :
String strObj = new String("Hello!");
String str = "Hello!";
// The two string references point two strings that are equal
if (strObj.equals(str)) {
System.out.println("The strings are equal");
}
// The two string references do not point to the same object
if (strObj != str) {
System.out.println("The strings are not the same object");
}
// If we intern a string that is equal to a given literal, the result is
// a string that has the same reference as the literal.
String internedStr = strObj.intern();
if (internedStr == str) {
System.out.println("The interned string and the literal are the same object");
}
내부적으로 메커니즘은 여전히 도달 할 수있는 모든 내부 문자열을 포함하는 해시 테이블을 유지합니다. String
에 대해 intern()
을 호출하면 메서드는 해시 테이블에서 객체를 찾습니다.
- 문자열이 발견되면 해당 값은 내부 문자열로 반환됩니다.
- 그렇지 않으면 문자열의 복사본이 해시 테이블에 추가되고 해당 문자열이 인턴 된 문자열로 반환됩니다.
==
사용하여 문자열을 비교할 수 있도록 interning을 사용할 수 있습니다. 그러나 이렇게하는 데는 중대한 문제가 있습니다. Pitfall - 인터 네거티브 문자열 을 참조하십시오. ==를 사용하면 자세한 내용을 알 수 없습니다. 대부분의 경우 권장되지 않습니다.
String 내의 문자의 대 / 소문자 변경
String
유형은 문자열을 대문자와 소문자로 변환하는 두 가지 방법을 제공합니다.
-
toUpperCase
- 모든 문자를 대문자로 변환합니다. -
toLowerCase
를 사용하여 모든 문자를 소문자로 변환
이러한 메소드는 모두 변환 된 문자열을 새 String
인스턴스로 반환합니다. String
은 Java에서 불변이므로 원래 String
객체는 수정되지 않습니다. 불변성에 대한 자세한 내용 은 자바 문자열의 불변성을 참조하십시오.
String string = "This is a Random String";
String upper = string.toUpperCase();
String lower = string.toLowerCase();
System.out.println(string); // prints "This is a Random String"
System.out.println(lower); // prints "this is a random string"
System.out.println(upper); // prints "THIS IS A RANDOM STRING"
숫자 및 구두점과 같은 알파벳이 아닌 문자는이 방법의 영향을받지 않습니다. 이러한 방법은 특정 조건에서 특정 유니 코드 문자를 잘못 처리 할 수도 있습니다.
주 :이 메소드는 로케일 에 의존적이므로, 로케일과는 별도로 해석되는 문자열에 사용하면 예기치 않은 결과가 발생할 수 있습니다. 예로는 프로그래밍 언어 식별자, 프로토콜 키 및 HTML
태그가 있습니다.
예를 들어, 터키어 로켈의 "TITLE".toLowerCase()
는 " tıtle
"을 반환합니다. 여기서 ı (\u0131)
은 라틴 소문자 DOTLESS I 문자입니다. 로케일에 영향을 Locale.ROOT
않는 문자열에 대해 올바른 결과를 얻으려면 Locale.ROOT
를 해당 대소 문자 변환 방법 (예 : toLowerCase(Locale.ROOT)
또는 toUpperCase(Locale.ROOT)
)에 대한 매개 변수로 전달 Locale.ROOT
.
Locale.ENGLISH
사용 Locale.ENGLISH
것이 대부분의 경우에도 올바르지 만, 언어가 변하지 않는 방법은 Locale.ROOT
입니다.
특수 대소 문자가 필요한 유니 코드 문자의 자세한 목록은 Unicode Consortium 웹 사이트 에서 찾을 수 있습니다.
ASCII 문자열에서 특정 문자의 대 / 소문자 변경 :
다음과 같은 알고리즘을 사용하여 ASCII 문자열의 특정 문자의 대 / 소문자를 변경하는 방법은 다음과 같습니다.
단계 :
- 문자열을 선언하십시오.
- 문자열을 입력하십시오.
- 캐릭터 라인을 문자 배열로 변환합니다.
- 검색 할 문자를 입력하십시오.
- 문자 배열로 문자를 검색합니다.
- 발견되면 문자가 소문자 또는 대문자인지 확인하십시오.
- 대문자 인 경우 문자의 ASCII 코드에 32를 추가하십시오.
- 소문자 인 경우 문자의 ASCII 코드에서 32를 뺍니다.
- 문자 배열에서 원래 문자를 변경하십시오.
- 문자 배열을 다시 문자열로 변환하십시오.
보일 라, 캐릭터의 경우가 변경되었습니다.
알고리즘 코드의 예는 다음과 같습니다.
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the String");
String s = scanner.next();
char[] a = s.toCharArray();
System.out.println("Enter the character you are looking for");
System.out.println(s);
String c = scanner.next();
char d = c.charAt(0);
for (int i = 0; i <= s.length(); i++) {
if (a[i] == d) {
if (d >= 'a' && d <= 'z') {
d -= 32;
} else if (d >= 'A' && d <= 'Z') {
d += 32;
}
a[i] = d;
break;
}
}
s = String.valueOf(a);
System.out.println(s);
다른 문자열 내에서 문자열 찾기
특정 문자열 a
가 문자열 b
에 포함되는지 여부를 확인하려면 다음 구문과 함께 String.contains()
메서드를 사용할 수 있습니다.
b.contains(a); // Return true if a is contained in b, false otherwise
String.contains()
메서드를 사용하면 CharSequence
를 문자열에서 찾을 수 있는지 확인할 수 있습니다. 방법은 문자열을 찾습니다 문자열에서 a
b
대소 문자를 구분하는 방법이다.
String str1 = "Hello World";
String str2 = "Hello";
String str3 = "helLO";
System.out.println(str1.contains(str2)); //prints true
System.out.println(str1.contains(str3)); //prints false
String이 다른 String 내에서 시작되는 정확한 위치를 찾으려면 String.indexOf()
.
String s = "this is a long sentence";
int i = s.indexOf('i'); // the first 'i' in String is at index 2
int j = s.indexOf("long"); // the index of the first occurrence of "long" in s is 10
int k = s.indexOf('z'); // k is -1 because 'z' was not found in String s
int h = s.indexOf("LoNg"); // h is -1 because "LoNg" was not found in String s
String.indexOf()
메서드는 char
또는 String
의 첫 번째 인덱스를 다른 String
반환합니다. 메소드가 발견되지 않으면 -1
리턴합니다.
참고 : String.indexOf()
메서드는 대 / 소문자를 구분합니다.
사례 무시 무시 검색의 예 :
String str1 = "Hello World";
String str2 = "wOr";
str1.indexOf(str2); // -1
str1.toLowerCase().contains(str2.toLowerCase()); // true
str1.toLowerCase().indexOf(str2.toLowerCase()); // 6
String의 길이를 얻는다.
a의 길이를 얻기 위하여 String
개체를 부르는 length()
거기에 방법을. 길이는 문자열의 UTF-16 코드 단위 (문자) 수와 같습니다.
String str = "Hello, World!";
System.out.println(str.length()); // Prints out 13
String의 char
는 UTF-16 값입니다. 값이 0x1000 이상인 유니 코드 코드 포인트 (예 : 대부분의 이모티콘)는 두 가지 문자 위치를 사용합니다. 각 코드 포인트가 UTF-16 char
값에 맞는지 여부에 관계없이 String에서 유니 코드 코드 포인트 수를 계산하려면 codePointCount
메서드를 사용할 수 있습니다.
int length = str.codePointCount(0, str.length());
자바 8에서 코드 포인트 스트림을 사용할 수도 있습니다.
int length = str.codePoints().count();
하위 문자열
String s = "this is an example";
String a = s.substring(11); // a will hold the string starting at character 11 until the end ("example")
String b = s.substring(5, 10); // b will hold the string starting at character 5 and ending right before character 10 ("is an")
String b = s.substring(5, b.length()-3); // b will hold the string starting at character 5 ending right before b' s lenght is out of 3 ("is an exam")
하위 문자열을 슬라이스하고 원래의 String에 문자를 추가 / 대체 할 수도 있습니다. 예를 들어, 한자를 포함하는 중국어 날짜를 직면했지만 올바른 형식의 날짜 문자열로 저장하려고합니다.
String datestring = "2015年11月17日"
datestring = datestring.substring(0, 4) + "-" + datestring.substring(5,7) + "-" + datestring.substring(8,10);
//Result will be 2015-11-17
substring 메서드는 String
조각을 추출합니다. 하나의 매개 변수가 제공되면 매개 변수는 시작이고 조각은 String
의 끝까지 확장됩니다. 두 개의 매개 변수가 주어지면 첫 번째 매개 변수는 시작 문자이고 두 번째 매개 변수는 끝 부분의 문자 (색인의 문자는 포함되지 않음)입니다. 쉬운 방법은 두 번째 매개 변수에서 첫 번째 매개 변수를 빼서 문자열의 예상 길이를 산출해야한다는 것입니다.
JDK <7u6 버젼에서는, substring
메소드는, 원의 String
와 같은 배킹 char[]
를 공유하는 String
를 인스턴스화 해, 내부의 offset
및 count
필드를 결과의 start 및 length로 설정합니다. 이러한 공유는 new String(s.substring(...))
을 호출하여 복사본 만들기를 방지함으로써 메모리 누수를 유발할 수 있으며 그 후에 char[]
가 가비지 수집 될 수 있습니다.
JDK 7u6에서 substring
메서드는 항상 기본 char[]
배열 전체를 복사하여 복잡성을 이전 상수와 비교하여 선형으로 만들었지 만 동시에 메모리 누수가 없음을 보장합니다.
문자열에서 n 번째 문자 가져 오기
String str = "My String";
System.out.println(str.charAt(0)); // "M"
System.out.println(str.charAt(1)); // "y"
System.out.println(str.charAt(2)); // " "
System.out.println(str.charAt(str.length-1)); // Last character "g"
문자열의 n 번째 문자를 얻으려면, 단순히 호출 charAt(n)
A의 String
, n
사용자가 검색하고자하는 문자의 인덱스입니다
참고 : 인덱스 n
은 0
에서 시작하므로 첫 번째 요소는 n = 0에 있습니다.
플랫폼 독립적 인 새 줄 구분 기호
새 광고 세퍼레이터, 플랫폼 (예 다르므로 \n
시스템 또는 유닉스에 \r\n
그것을 액세스 플랫폼에 독립적 인 방법을 갖는 것이 필요하다 윈도우 온). Java에서는 시스템 속성에서 검색 할 수 있습니다.
System.getProperty("line.separator")
새 줄 구분 기호가 매우 일반적으로 필요하기 때문에 위의 코드와 정확히 같은 결과를 반환하는 바로 가기 메서드의 Java 7부터 사용할 수 있습니다.
System.lineSeparator()
참고 : 프로그램을 실행하는 동안 줄 바꿈 기호가 변경되는 경우는 거의 없으므로 필요할 때마다 시스템 속성에서 가져 오는 대신 정적 최종 변수에 저장하는 것이 좋습니다.
String.format
을 사용할 때 \n
또는 '\ r \ n'대신 %n
사용하여 플랫폼 독립적 인 새 줄 구분 기호를 출력하십시오.
System.out.println(String.format('line 1: %s.%nline 2: %s%n', lines[0],lines[1]));
커스텀 객체를위한 toString () 메소드 추가하기
다음 Person
클래스를 정의했다고 가정 해보십시오.
public class Person {
String name;
int age;
public Person (int age, String name) {
this.age = age;
this.name = name;
}
}
새 Person
객체를 인스턴스화하는 경우
Person person = new Person(25, "John");
나중에 코드를 사용하여 객체를 인쇄하려면 다음 문을 사용합니다.
System.out.println(person.toString());
다음과 비슷한 결과가 나옵니다.
Person@7ab89d
이는 Person
의 수퍼 클래스 Person
Object
클래스에 정의 된 toString()
메서드를 구현 한 결과입니다. Object.toString()
대한 설명은 다음과 같습니다.
Object 클래스의 toString 메서드는 객체가 인스턴스 인 클래스의 이름, at 기호 문자`@ '및 객체의 해시 코드의 부호없는 16 진수 표현으로 구성된 문자열을 반환합니다. 즉,이 메서드는 다음과 같은 문자열을 반환합니다.
getClass().getName() + '@' + Integer.toHexString(hashCode())
따라서 의미있는 출력을 얻으 려면 toString()
메서드를 재정의 해야합니다.
@Override
public String toString() {
return "My name is " + this.name + " and my age is " + this.age;
}
이제 결과는 다음과 같습니다.
My name is John and my age is 25
다음과 같이 쓸 수도 있습니다.
System.out.println(person);
실제로 println()
은 객체에 대해 toString
메서드를 암시 적으로 호출합니다.
문자열 분할
특정 구분 문자 나 정규 표현식 에 String
을 분할 할 수 있으며 다음과 같은 서명이있는 String.split()
메서드를 사용할 수 있습니다.
public String[] split(String regex)
문자 또는 정규식의 분리는 결과 문자열 배열에서 제거됩니다.
구분 문자를 사용하는 예 :
String lineFromCsvFile = "Mickey;Bolton;12345;121216";
String[] dataCells = lineFromCsvFile.split(";");
// Result is dataCells = { "Mickey", "Bolton", "12345", "121216"};
정규 표현식을 사용한 예 :
String lineFromInput = "What do you need from me?";
String[] words = lineFromInput.split("\\s+"); // one or more space chars
// Result is words = {"What", "do", "you", "need", "from", "me?"};
String
리터럴을 직접 분리 할 수도 있습니다.
String[] firstNames = "Mickey, Frank, Alicia, Tom".split(", ");
// Result is firstNames = {"Mickey", "Frank", "Alicia", "Tom"};
경고 : 매개 변수가 항상 정규 표현식으로 처리된다는 사실을 잊지 마십시오.
"aaa.bbb".split("."); // This returns an empty array
앞의 예에서 .
는 모든 문자와 일치하는 정규 표현식 와일드 카드로 취급되며 모든 문자는 구분 기호이므로 결과는 빈 배열입니다.
정규식 메타 문자 인 구분 기호를 기반으로 분할
다음 문자는 정규 표현식에서 특수 문자 (일명 메타 문자)로 간주됩니다.
< > - = ! ( ) [ ] { } \ ^ $ | ? * + .
위의 구분 기호 중 하나를 기반으로 문자열을 분할하려면 \\
사용하여 이스케이프 하거나 Pattern.quote()
사용해야합니다.
Pattern.quote()
:String s = "a|b|c"; String regex = Pattern.quote("|"); String[] arr = s.split(regex);
특수 문자 이스케이프 :
String s = "a|b|c"; String[] arr = s.split("\\|");
Split은 빈 값을 제거합니다.
split(delimiter)
는 기본적으로 결과 배열에서 후행 빈 문자열을 제거합니다. 이 메커니즘을 끄려면 다음과 같이 음수 값으로 설정된 split(delimiter, limit)
가있는 split(delimiter, limit)
의 오버로드 된 버전을 사용해야합니다.
String[] split = data.split("\\|", -1);
split(regex)
는 split(regex, 0)
결과를 내부적으로 반환합니다.
limit 매개 변수는 패턴 적용 횟수를 제어하므로 결과 배열의 길이에 영향을줍니다.
한계 n 이 0보다 큰 경우 패턴은 최대 n - 1 회 적용되고 배열의 길이는 n 보다 크지 않으며 배열의 마지막 항목에는 마지막으로 일치하는 구분 기호 이후의 모든 입력이 포함됩니다.
n 가 부의 경우, 패턴은 가능한 한 많은 회수에 적용되어 배열은 임의의 길이를 가질 수가 있습니다.
n 가 제로의 경우, 패턴은 가능한 한 많이 적용되어 배열은 임의의 길이를 가질 수가있어 공백의 캐릭터 라인은 파기됩니다.
StringTokenizer
분할하기
split()
메서드 외에 StringTokenizer
사용하여 문자열을 분할 할 수도 있습니다.
StringTokenizer
는 String.split()
보다 훨씬 제한적이며 사용하기가 조금 더 어렵습니다. 이것은 본질적으로 고정 된 문자 세트 ( String
주어진)로 구분 된 토큰을 추출하기 위해 설계되었습니다. 각 문자는 구분 기호로 사용됩니다. 이 제한 때문에 String.split()
보다 약 두 배 빠릅니다.
기본 문자 집합은 빈 칸 ( \t\n\r\f
)입니다. 다음 예제는 각 단어를 개별적으로 출력합니다.
String str = "the lazy fox jumped over the brown fence";
StringTokenizer tokenizer = new StringTokenizer(str);
while (tokenizer.hasMoreTokens()) {
System.out.println(tokenizer.nextToken());
}
그러면 다음과 같이 인쇄됩니다.
the
lazy
fox
jumped
over
the
brown
fence
분리를 위해 다른 문자 세트를 사용할 수 있습니다.
String str = "jumped over";
// In this case character `u` and `e` will be used as delimiters
StringTokenizer tokenizer = new StringTokenizer(str, "ue");
while (tokenizer.hasMoreTokens()) {
System.out.println(tokenizer.nextToken());
}
그러면 다음과 같이 인쇄됩니다.
j
mp
d ov
r
분리 문자로 문자열 조인
문자열 배열은 정적 메서드 String.join()
사용하여 조인 할 수 있습니다.
String[] elements = { "foo", "bar", "foobar" };
String singleString = String.join(" + ", elements);
System.out.println(singleString); // Prints "foo + bar + foobar"
마찬가지로 Iterable
대한 오버로드 된 String.join()
메서드가 있습니다.
조인을 세부적으로 제어하려면 StringJoiner 클래스를 사용할 수 있습니다.
StringJoiner sj = new StringJoiner(", ", "[", "]");
// The last two arguments are optional,
// they define prefix and suffix for the result string
sj.add("foo");
sj.add("bar");
sj.add("foobar");
System.out.println(sj); // Prints "[foo, bar, foobar]"
문자열 스트림에 참여하려면 가입 콜렉터를 사용할 수 있습니다.
Stream<String> stringStream = Stream.of("foo", "bar", "foobar");
String joined = stringStream.collect(Collectors.joining(", "));
System.out.println(joined); // Prints "foo, bar, foobar"
여기에는 접두사와 접미사 를 정의 할 수있는 옵션이 있습니다.
Stream<String> stringStream = Stream.of("foo", "bar", "foobar");
String joined = stringStream.collect(Collectors.joining(", ", "{", "}"));
System.out.println(joined); // Prints "{foo, bar, foobar}"
반전 문자열
문자열을 역순으로 되돌릴 수있는 몇 가지 방법이 있습니다.
StringBuilder / StringBuffer :
String code = "code"; System.out.println(code); StringBuilder sb = new StringBuilder(code); code = sb.reverse().toString(); System.out.println(code);
문자 배열 :
String code = "code"; System.out.println(code); char[] array = code.toCharArray(); for (int index = 0, mirroredIndex = array.length - 1; index < mirroredIndex; index++, mirroredIndex--) { char temp = array[index]; array[index] = array[mirroredIndex]; array[mirroredIndex] = temp; } // print reversed System.out.println(new String(array));
문자열의 하위 문자열 또는 문자 발생 계산
org.apache.commons.lang3.StringUtils의 countMatches
메소드는 대개 String
의 하위 문자열 또는 문자 발생을 계산하는 데 사용됩니다.
import org.apache.commons.lang3.StringUtils;
String text = "One fish, two fish, red fish, blue fish";
// count occurrences of a substring
String stringTarget = "fish";
int stringOccurrences = StringUtils.countMatches(text, stringTarget); // 4
// count occurrences of a char
char charTarget = ',';
int charOccurrences = StringUtils.countMatches(text, charTarget); // 3
그렇지 않으면 표준 Java API와 동일하게 정규 표현식을 사용할 수 있습니다.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
String text = "One fish, two fish, red fish, blue fish";
System.out.println(countStringInString("fish", text)); // prints 4
System.out.println(countStringInString(",", text)); // prints 3
public static int countStringInString(String search, String text) {
Pattern pattern = Pattern.compile(search);
Matcher matcher = pattern.matcher(text);
int stringOccurrences = 0;
while (matcher.find()) {
stringOccurrences++;
}
return stringOccurrences;
}
문자열 연결 및 StringBuilders
+
연산자를 사용하여 문자열 연결을 수행 할 수 있습니다. 예 :
String s1 = "a";
String s2 = "b";
String s3 = "c";
String s = s1 + s2 + s3; // abc
일반적으로 컴파일러 구현은 후드 아래에 StringBuilder
가 포함 된 메서드를 사용하여 위의 연결을 수행합니다. 컴파일 될 때 코드는 다음과 비슷하게 보입니다.
StringBuilder sb = new StringBuilder("a");
String s = sb.append("b").append("c").toString();
StringBuilder
에는 여러 유형을 추가하기위한 오버로드 된 메소드가 여러 개 있습니다. 예를 들어, String
대신 int
를 추가 할 수 있습니다. 예를 들어, 구현은 다음을 변환 할 수 있습니다.
String s1 = "a";
String s2 = "b";
String s = s1 + s2 + 2; // ab2
다음에 :
StringBuilder sb = new StringBuilder("a");
String s = sb.append("b").append(2).toString();
위의 예제는 코드의 단일 위치에서 효과적으로 수행되는 간단한 연결 작업을 보여줍니다. 연결에는 StringBuilder
의 단일 인스턴스가 포함됩니다. 경우에 따라 연결은 루프와 같이 누적 방식으로 수행됩니다.
String result = "";
for(int i = 0; i < array.length; i++) {
result += extractElement(array[i]);
}
return result;
이 경우 일반적으로 컴파일러 최적화는 적용되지 않으며 각 반복마다 새 StringBuilder
객체가 만들어집니다. 이것은 단일 StringBuilder
를 사용하도록 코드를 명시 적으로 변환하여 최적화 할 수 있습니다.
StringBuilder result = new StringBuilder();
for(int i = 0; i < array.length; i++) {
result.append(extractElement(array[i]));
}
return result.toString();
StringBuilder
는 16 자의 빈 공간으로 초기화됩니다. 큰 문자열을 작성한다는 것을 미리 아는 경우에는 내부 버퍼를 크기 조정할 필요가 없도록 사전에 충분한 크기로 초기화하는 것이 좋습니다.
StringBuilder buf = new StringBuilder(30); // Default is 16 characters
buf.append("0123456789");
buf.append("0123456789"); // Would cause a reallocation of the internal buffer otherwise
String result = buf.toString(); // Produces a 20-chars copy of the string
많은 문자열을 생성하는 경우 StringBuilder
를 다시 사용하는 것이 좋습니다.
StringBuilder buf = new StringBuilder(100);
for (int i = 0; i < 100; i++) {
buf.setLength(0); // Empty buffer
buf.append("This is line ").append(i).append('\n');
outputfile.write(buf.toString());
}
다수의 스레드가 동일한 버퍼에 기록된다 (그리고에만) 있으면 사용 StringBuffer와 A는, synchronized
버전 StringBuilder
. 그러나 일반적으로 하나의 스레드 만 버퍼에 쓰기 때문에 일반적으로 동기화없이 StringBuilder
를 사용하는 것이 더 빠릅니다.
concat () 메소드 사용 :
String string1 = "Hello ";
String string2 = "world";
String string3 = string1.concat(string2); // "Hello world"
이렇게하면 끝에 string2가 추가 된 string1 인 새 문자열이 반환됩니다. 다음과 같이 concat () 메서드를 문자열 리터럴과 함께 사용할 수도 있습니다.
"My name is ".concat("Buyya");
문자열 부분 바꾸기
정규식 또는 완전 일치로 대체하는 두 가지 방법.
주 : 원래 String 오브젝트는 변경되지 않고 리턴 값은 변경된 String을 보유합니다.
정확히 일치
한 문자를 다른 한 문자로 바꾸기 :
String replace(char oldChar, char newChar)
이 캐릭터 라인의 oldChar가 모두 newChar로 옮겨져 결과적으로 새로운 캐릭터 라인을 돌려줍니다.
String s = "popcorn";
System.out.println(s.replace('p','W'));
결과:
WoWcorn
문자 시퀀스를 다른 문자 시퀀스로 바꿉니다.
String replace(CharSequence target, CharSequence replacement)
리터럴 대상 시퀀스와 일치하는이 문자열의 각 부분 문자열을 지정된 리터럴 대체 시퀀스로 바꿉니다.
String s = "metal petal et al.";
System.out.println(s.replace("etal","etallica"));
결과:
metallica petallica et al.
정규식
참고 : 그룹화는 $
문자를 사용하여 $1
과 같은 그룹을 참조합니다.
모든 일치 항목 바꾸기 :
String replaceAll(String regex, String replacement)
지정된 정규 표현식과 일치하는이 문자열의 각 부분 문자열을 지정된 대체 문자열로 바꿉니다.
String s = "spiral metal petal et al.";
System.out.println(s.replaceAll("(\\w*etal)","$1lica"));
결과:
spiral metallica petallica et al.
첫 번째 일치 만 바꾸기 :
String replaceFirst(String regex, String replacement)
지정된 정규 표현식과 일치하는이 문자열의 첫 번째 부분 문자열을 지정된 대체 문자열로 바꿉니다.
String s = "spiral metal petal et al.";
System.out.println(s.replaceAll("(\\w*etal)","$1lica"));
결과:
spiral metallica petal et al.
문자열의 시작과 끝에서 공백 제거
trim()
메소드는 선행 및 후행 공백이 제거 된 새로운 String을 리턴합니다.
String s = new String(" Hello World!! ");
String t = s.trim(); // t = "Hello World!!"
제거 할 공백이없는 문자열을 trim
동일한 String 인스턴스가 반환됩니다.
trim()
메서드 는 Character.isWhitespace()
메서드에서 사용하는 개념과는 다른 고유 한 공백 개념을 가지고 있습니다 .
U+0000
에서U+0020
까지의 모든 ASCII 제어 문자는 공백으로 간주되어trim()
의해 제거됩니다. 여기에는U+0020 'SPACE'
,U+0009 'CHARACTER TABULATION'
,U+000A 'LINE FEED'
및U+000D 'CARRIAGE RETURN'
문자뿐 아니라U+0007 'BELL'
과 같은 문자가 포함됩니다.U+00A0 'NO-BREAK SPACE'
또는U+2003 'EM SPACE'
와 같은 유니 코드 공백은trim()
의해 인식 되지 않습니다 .
문자열 풀 및 힙 저장소
많은 Java 객체와 마찬가지로, 모든 String
인스턴스는 힙에, 심지어 리터럴로 만들어집니다. JVM에서이 발견되면 String
힙에 상응하는 기준이없는 리터럴은 JVM은 해당 생성 String
힙 인스턴스 그것도 새롭게 생성 된 참조 저장 String
문자열 풀의 인스턴스. 동일한 String
리터럴에 대한 다른 참조는 힙의 이전에 작성된 String
인스턴스로 대체됩니다.
다음 예제를 살펴 보겠습니다.
class Strings
{
public static void main (String[] args)
{
String a = "alpha";
String b = "alpha";
String c = new String("alpha");
//All three strings are equivalent
System.out.println(a.equals(b) && b.equals(c));
//Although only a and b reference the same heap object
System.out.println(a == b);
System.out.println(a != c);
System.out.println(b != c);
}
}
위의 출력은 다음과 같습니다.
true
true
true
true
큰 따옴표를 사용하여 문자열을 만들면 String 풀에서 동일한 값을 가진 String을 먼저 찾습니다. 발견되면 풀에 새 String을 만든 다음 참조를 반환합니다.
그러나 new 연산자를 사용하여 String 클래스가 힙 공간에 새 String 객체를 만들도록합니다. 우리는 intern () 메서드를 사용하여 풀에 넣거나 동일한 값을 가진 문자열 풀에서 다른 String 객체를 참조 할 수 있습니다.
String 풀 자체도 힙에 만들어집니다.
Java 7 이전에는 String
리터럴 이 고정 된 크기를 갖는 PermGen
의 메소드 영역에 런타임 상수 풀에 저장되었습니다.
String 풀은 PermGen
있었습니다.
JDK 7에서 interned 문자열은 더 이상 Java 힙의 영구 생성에 할당되지 않지만 응용 프로그램에서 생성 된 다른 객체와 함께 Java 힙의 주요 부분 (젊은 세대와 구세대로 알려짐)에 할당됩니다 . 이 변경으로 인해 메인 Java 힙에 더 많은 데이터가 저장되고 영구 생성에서는 데이터가 줄어들어 힙 크기를 조정해야 할 수 있습니다. 대부분의 응용 프로그램에서는이 변경으로 인해 힙 사용이 상대적으로 작은 차이 만 표시되지만 많은 클래스를로드하거나
String.intern()
메서드를 많이 사용하는 응용 프로그램이 더 큰 차이를 보입니다.
대소 문자를 구분하지 않는 스위치
switch
자체는 대 / 소문자를 구분하지 않고 매개 변수화 할 수 없지만 꼭 필요한 경우 toLowerCase()
또는 toUpperCase
사용하여 입력 문자열에 대해 구분하지 않습니다.
switch (myString.toLowerCase()) {
case "case1" :
...
break;
case "case2" :
...
break;
}
주의
-
Locale
은 사건의 변화에 영향을 미칠 수 있습니다! - 레이블에는 대문자가 포함되지 않도록주의해야합니다. 절대 실행되지 않습니다!