(1) Regular Expression - 특정한 규칙을 가진 문자열의 집합을 표현하기 위해 쓰이는 것
(어떤 텍스트 내에서 특정한 형태나 규칙을 가진 문자열을 찾기 위해 그 형태나 규칙을 나타내는 패턴을 정의)
Q. 언제 사용?
> 텍스트 처리 작업에 유용
> 데이터 검증 (주민번호, 휴대폰 번호 등)에 사용
^
|
문자열 시작
|
$
|
문자열 종료
|
.
|
임의의 문자 [단 ‘'는 넣을 수 없습니다.]
|
*
|
앞 문자가 0개 이상의 개수가 존재할 수 있습니다.
|
+
|
앞 문자가 1개 이상의 개수가 존재할 수 있습니다.
|
?
|
앞 문자가 없거나 하나 있을 수 있습니다.
|
[]
|
문자의 집합이나 범위를 표현합니다. -기호를 통해 범위를 나타낼 수 있습니다. ^가 존재하면 not을 나타냅니다.
|
{}
|
횟수 또는 범위를 나타냅니다.
|
()
|
괄호안의 문자를 하나의 문자로 인식합니다.
|
|
|
패턴을 OR 연산을 수행할 때 사용합니다.
|
\s
|
공백 문자
|
\S
|
공백 문자가 아닌 나머지 문자
|
\w
|
알파벳이나 문자
|
\W
|
알파벳이나 숫자를 제외한 문자
|
\d
|
[0-9] 숫자
|
\D
|
숫자를 제외한 모든 문자
|
(?i)
|
대소문자를 구분하지 않습니다.
|
(2) String, StringBuffer, StringBuilder
<String의 문제점>
메모리를 과소비한다. 처음 데이터에 변화가 생기면 기존 메모리 공간을 그대로 두고, 새로운 데이터를 새로운 메모리에 할당한다. 속도가 느려짐....
<String의 대안으로 StringBuffer, StringBuilder가 등장>
Q. 공통점?
모두 다 String 문자열을 저장하고 관리하는 클래스
Q. 차이점?
ⓐ String은 불변
ⓑ StringBuffer,StringBuilder은 가변 - 자기 자신을 리턴하여 계속해서 자신의 메소드를 호출
ⓒ StringBuffer, StringBuilder는 new 연산자로 객체 생성을 해야 한다.
StringBuilder : 동기화x, ,문자열 조작 속도가 빠르다.
VS
StringBuffer : string을 임시로 저장하는 공간, 동기화o, 쓰레드(다중작업)에서 안전, 속도가 느리다.
------------------------------------------------------------------------------
String 클래스 : 문자열 연산이 적고 조회가 많을 때 멀티쓰레드 환경에서 사용
VS
StringBuffer : 문자열 연산이 많을 때 or 멀티쓰레드환경에서 사용
VS
StringBuilder : 싱글쓰레드 or 쓰레드를 신경쓰지 않아도 되는 환경에서 사용
* 문자열과 문자열을 더하게 되면 내부적으로는 스트링버퍼가 매번 실행된다.
(java에서 많은 new를 만드는 것은 속도를 느리게 하는 원인 !!! )
또한, 문자열을 반복문에서 더하는 것은 비효율적인 코드이기 때문에 다음과 같이 하는 것이 효율적!!
public class StringBufferExam {
public static void main(String[] args) {
String str1 = "hello world";
String str2 = str1.substring(5);
String str3 = str1 + str2; // + 연산 비효율적
System.out.println(str3);
// str3 내부적으로 실행되는 코드, 매번 문자열을 append할 때마다 new StringBuffer가 실행 (비효율적)
String str3 = new StringBuffer().append(str1).append(str2).toString();
String str="";
for(int i=0;i<100;i++){
str=str+"*";
}
//String 변수 생성해서 StringBuffer의 toString()호출해서 String으로 리턴받게끔 (효율)
//StringBuffer가 한 번만 실행 되니까!!!
StringBuffer sb = new StringBuffer();
for (int i = 0;i<100 ;i++ ){
sb.append("*");
}
System.out.println(sb);
String str = sb.toString();
System.out.print(str);
}
}
---------- run ----------
hello world world
****************************************************************************************************
****************************************************************************************************
- indexOf(String str) - 스페이스바도 계산
- indexOf(String str, int fromIndex) - ~번째 이후에 있는 문자열 출력
- isEmpty() - 문자열이 비어있는지 (is는 boolean값을 리턴)
public class StringTest5 {
public static void main(String[] args) {
//indexOf(String str) - 스페이스바도 계산
String str = "hallo java !!!";
System.out.println("1.str에서 o는 " + str.indexOf("o") + "번째 있습니다.");
System.out.println("2.str에서 o는 " + str.indexOf('o') + "번째 있습니다."); //문자는 ascii code값이 있기 때문에 ok
System.out.println("3.str에서 java는 " + str.indexOf("java") + "번째 있습니다.");
System.out.println("4.str에서 a는 " + str.indexOf("a") + "번째 있습니다.");
System.out.println("5.str에서 a는 " + str.lastIndexOf("a") + "번째 있습니다."); //마지막 a 위치 출력
//indexOf(String str, int fromIndex) - ~번째 이후에 있는 문자열 출력
System.out.println("6.str에서 4번째 이후에 있는 a는 " + str.indexOf("a",4) + "번째 있습니다.");
//isEmpty() - 문자열이 비어있는지 (is는 boolean값을 리턴)
if(str.isEmpty())
System.out.println("7.str은 빈문자열입니다."); //x
str = new String(); //or str = "";
if(str.isEmpty())
System.out.println("8.변경후 str은 빈문자열입니다.");
//String numStr = "123";
//String numStr = "1a3";
//String numStr = "";
String numStr = null;
boolean flag = false;
if (numStr != null && !numStr.isEmpty()){
flag = true;
int len = numStr.length(); //이렇게 len으로 변수 잡아주는 것이 시간을 줄일 수 있다!!
for(int i=0;i<len;i++) {
int ascii = numStr.charAt(i);
if(ascii < 48 || ascii > 57) { //48은 0, 57은 9 - 음수거나 9보다 크다면 ?
flag = false;
break;
}
}
}
if (flag){
System.out.println("9." + numStr + "은 숫자입니다.");
} else {
System.out.println("10." + numStr + "은 숫자가 아닙니다.");
}
//123은 숫자입니다.
//1a3은 숫자가 아닙니다.
}
}
---------- run ----------
1.str에서 o는 4번째 있습니다.
2.str에서 o는 4번째 있습니다.
3.str에서 java는 6번째 있습니다.
4.str에서 a는 1번째 있습니다.
5.str에서 a는 9번째 있습니다.
6.str에서 4번째 이후에 있는 a는 7번째 있습니다.
8.변경후 str은 빈문자열입니다.
10.null은 숫자가 아닙니다.
- replace(char oldChar, char newChar) - oldChar를 newChar로 문자를 바꿔라
- replaceAll(String regex, String replacement) - regax:정규표현식, 특정문자를 지정해서 모두(oldChar까지) 바꿔라
- split(String regex) = StringTokenizer : split과 비슷하지만, 더 많이 쓴다!!!
public class StringTest6 {
public static void main(String[] args) {
//replace(char oldChar, char newChar) - oldChar를 newChar로 문자를 바꿔라
String str = "hallo jaba!!!";
String str2 = str.replace('b','v');
System.out.println("1.str2 : " + str2);
String str3 = str2.replace("hallo","hello");
System.out.println("2.str3 : " + str3);
//replaceAll(String regex, String replacement) - regax:정규표현식, 특정문자를 지정해서 모두(oldChar까지) 바꿔라
String str4 = str2.replaceAll("hallo","hello");
System.out.println("3.str4 : " + str4);
System.out.println("-----------------------------");
//split(String regex) = StringTokenizer : split과 비슷하지만, 더 많이 쓴다!!!
String s[] = str4.split(" "); //스페이스바를 기준으로 잘라라
for (String msg : s){ //배열의 길이만큼 for문
System.out.println("4."+msg);
}
}
}
---------- run ----------
1.str2 : hallo java!!!
2.str3 : hello java!!!
3.str4 : hello java!!!
-----------------------------
4.hello
4.java!!!
- subSequence(int start, int end) : 해당 문자열을 자르고 싶다면,endIndex 전까지
- substring(int beginIndex, int endIndex) -- ~번째 까지[index] 문자열 자르기, 문자열로 바꿀 필요가 없다.
자체가 문자열 vs CharSequence -> string 문자열이라고 생각하기
- substring(int beginIndex) - 시작지점부터 끝까지 모두 출력
- trim() - 공백제거 : 문자와 문자사이는 x, 앞 뒤의 공백만 제거 (로그인시 주로 사용)
public class StringTest7 {
public static void main(String[] args) {
String str = "hello java!!!";
//subSequence(int start, int end)
CharSequence cs = str.subSequence(6,10); //해당 문자열을 자르고 싶다면,endIndex 전까지
String msg = cs.toString(); //toString 자동 호출
System.out.println("1."+msg); //인터페이스는 화면에 출력x, 그래서 toString()이라는 메소드 호출해야 함
//뽑아낸 문자열에서 a는 몇 번째?
int idx = msg.indexOf('a');
System.out.println("2.뽑아낸 문자열에서 a는 " + idx + "번째 입니다.");
//substring(int beginIndex, int endIndex) -- ~번째 까지[index] 문자열 자르기, 문자열로 바꿀 필요가 없다. 자체가 문자열 vs CharSequence
String substr1 = str.substring(6,10); //endIndex 앞까지 반영!!
System.out.println("3."+substr1);
idx = substr1.indexOf('a');
System.out.println("4.뽑아낸 문자열에서 a는 " + idx + "번째 입니다.");
//substring(int beginIndex) - 시작지점부터 끝까지 모두 출력
substr1 = str.substring(6);
System.out.println("5."+substr1);
//trim() - 공백제거 : 문자와 문자사이는 x, 앞 뒤의 공백만 제거
String s = "j ava";
System.out.println("6.s의 길이 : " + s.length());
System.out.println("7.s의 공백을 제거한 후 길이 : " + s.trim().length());
}
}
---------- run ----------
1.java
2.뽑아낸 문자열에서 a는 1번째 입니다.
3.java
4.뽑아낸 문자열에서 a는 1번째 입니다.
5.java!!!
6.s의 길이 : 7
7.s의 공백을 제거한 후 길이 : 7
- StringBuffer - 문자열 조작 class(가변 - 원본이 바뀜) VS String - 문자열 불변
- StringBuffer(), capacity() - 만들 때부터 16의 용량이 고정
- StringBuffer(int capacity)- 만들 때부터 용량 조절 가능
- StringBuffer(String str) - 주로 사용(만들 때부터 문자를 입력하고 추가 용량)
- append(String str) - 문자열 추가
- delete(int start, int end) - 범위를 지운다
- deleteCharAt(int index) - 문자 하나만 지우기
- insert(int offset, boolean b) - 중간에 끼워넣기
- replace(int start, int end, String str)
- reverse() - 한번에 문자열 뒤집기
- setCharAt(int index, char ch) - 인덱스에 있는 문자 한개만 바꾸기
- setLength(int newLength) - 글자수를 줄이기
public class StringBufferTest1 {
public static void main(String[] args) {
//StringBuffer - 문자열 조작 class(가변 - 원본이 바뀜) VS String - 문자열 불변
//StringBuffer(),capacity() - 만들 때부터 16의 용량이 고정
StringBuffer sb1 = new StringBuffer();
System.out.println("1.sb1의 초기 크기 : " + sb1.capacity());
//StringBuffer(int capacity) - 만들 때부터 용량 조절 가능
StringBuffer sb2 = new StringBuffer(20);
System.out.println("2.sb2의 초기 크기 : " + sb2.capacity());
//StringBuffer(String str) - 주로 사용 (만들 때부터 문자를 입력하고 추가 용량)
StringBuffer sb3 = new StringBuffer("hello ");
System.out.println("3.sb3의 초기 크기 : " + sb3.capacity()); //용량, 6+16 = 22
System.out.println("4.sb3의 문자 수 : " + sb3.length()); // 문자의 길이
//append(String str) - 뒤에 16칸이 생성되지 않고, 남은 16칸에서 줄어든다.
sb3.append("java");
System.out.println("5.sb3 : " + sb3); // or System.out.println("sb3 : " + sb3.append("java"));
System.out.println("6. 문자열 추가 후 크기 : " + sb3.capacity()); //크기는 같지만, 남은 용량은 12
System.out.println("7. 문자열 추가 후 문자수 : " + sb3.length());
sb3.append("!!!!!!!!!!!!");
System.out.println("8.문자열 추가 후 크기 : " + sb3.capacity()); //크기 = 문자수, 남은 용량 0
System.out.println("9.문자열 추가 후 문자수 : " + sb3.length());
//Buffer는 문자열이 작업 공간을 초과하면 자동으로 공간 2배로 늘려준다.
sb3.append("!!!!!!!!!!!!@");
System.out.println("10.문자열 추가 후 크기 : " + sb3.capacity());
System.out.println("11.문자열 추가 후 문자수 : " + sb3.length());
//메소드체이닝 - 자신의 메소드를 호출하여 자기 자신의 값을 바꿔나감
StringBuffer str2 = new StringBuffer().append("hello").append(" ").append("world");
//위에랑 같은코드 toString()의 return 변수를 잡아준 것
String str = new StringBuffer().append("hello").append(" ").append("world").toString();
//delete(int start, int end) - 범위를 지운다
sb3.append("!!@@@!!!!!@");
System.out.println("12.문자열 추가 후 크기 : " + sb3.capacity());
System.out.println("13.문자열 추가 후 문자수 : " + sb3.length());
System.out.println("14.sb3 : " + sb3);
System.out.println("15.sb3 : " + sb3.delete(12,15));
System.out.println("16.sb3 : " + sb3); //원본이 바뀐다!!!
//deleteCharAt(int index) - 문자 하나만 지우기
System.out.println("17.sb3 : " + sb3.deleteCharAt(17));
//insert(int offset, boolean b) - 중간에 끼워넣기
System.out.println("18.sb3 : " + sb3.insert(6,"good "));
//replace(int start, int end, String str)
System.out.println("19.sb3 : " + sb3.replace(6,10,"좋은"));
//reverse() - 한번에 문자열 뒤집기
//setCharAt(int index, char ch) - 인덱스에 있는 문자 한개만 바꾸기
//setLength(int newLength) - 글자수를 줄이기
}
}
---------- run ----------
1.sb1의 초기 크기 : 16
2.sb2의 초기 크기 : 20
3.sb3의 초기 크기 : 22
4.sb3의 문자 수 : 6
5.sb3 : hello java
6. 문자열 추가 후 크기 : 22
7. 문자열 추가 후 문자수 : 10
8.문자열 추가 후 크기 : 22
9.문자열 추가 후 문자수 : 22
10.문자열 추가 후 크기 : 46 (2배로 늘어남)
11.문자열 추가 후 문자수 : 35
12.문자열 추가 후 크기 : 46
13.문자열 추가 후 문자수 : 46
14.sb3 : hello java!!!!!!!!!!!!!!!!!!!!!!!!@!!@@@!!!!!@
15.sb3 : hello java!!!!!!!!!!!!!!!!!!!!!@!!@@@!!!!!@
16.sb3 : hello java!!!!!!!!!!!!!!!!!!!!!@!!@@@!!!!!@
17.sb3 : hello java!!!!!!!!!!!!!!!!!!!!@!!@@@!!!!!@
18.sb3 : hello good java!!!!!!!!!!!!!!!!!!!!@!!@@@!!!!!@
19.sb3 : hello 좋은 java!!!!!!!!!!!!!!!!!!!!@!!@@@!!!!!@
//문자열을 더할때(다중작업)는 builder 쓰는 것이 가장 효율적
public class StringVSBuffer {
public static void main(String[] args) {
long st = System.nanoTime();
String str = "number : ";
for (int i=1;i<1001 ;i++ ){
str += i + "";
}
System.out.println("String : " + (System.nanoTime() - st)); //for문이 도는 시간
//System.out.println(str);
st = System.nanoTime();
StringBuffer buffer = new StringBuffer("number : ");
for (int i=1;i<1001 ;i++ ){
buffer.append(i);
}
System.out.println("StringBuffer : " + (System.nanoTime() - st));
//System.out.println(buffer);
st = System.nanoTime();
StringBuilder builder = new StringBuilder("number : ");
for (int i=1;i<1001 ;i++ ){
builder.append(i);
}
System.out.println("StringBuilder : " + (System.nanoTime() - st));
//System.out.println(builder);
}
}
---------- run ----------
String : 9364700
StringBuffer : 254400
StringBuilder : 120500
(3) StringTokenizer : 문자열을 나눌 때 사용
package test07;
import java.util.*;
public class StringEx {
public static void main(String[] args) {
String str1 = "오늘 날씨는 춥고, 눈이 많이 옵니다.";
String str2 = "2019/11/08";
System.out.println(str1);
System.out.println(str2);
StringTokenizer tokenizer1 = new StringTokenizer(str1); //default는 띄어쓰기 기준
StringTokenizer tokenizer2 = new StringTokenizer(str2, "/");
System.out.println("tokenizer1 문자열 수" + tokenizer1.countTokens()); //7
System.out.println("tokenizer2 문자열 수" + tokenizer2.countTokens()); //3
while(tokenizer1.hasMoreTokens()) {
System.out.println(tokenizer1.nextToken());
}
while(tokenizer2.hasMoreTokens()) {
System.out.println(tokenizer2.nextToken());
}
}
}
오늘 날씨는 춥고, 눈이 많이 옵니다.
2019/11/08
tokenizer1 문자열 수 : 6
tokenizer2 문자열 수 : 3
오늘
날씨는
춥고,
눈이
많이
옵니다.
2019
11
08