배열(Array)
1. 같은 이름으로 정의된 연속적인 공간이다.
변수는 1개의 데이터 밖에 저장하지 못한다.
배열을 이용하면 변수가 가진 약점을 보완할 수 있다.
많은 양의 데이터를 다룰 수 있도록 하기 위해서 배열을 쓴다.
2. 객체로 취급
객체로 취급한다는 것은 클래스로 만들어 놓았다는 이야기이다.
클래스는 변수와 메소드를 묶어준다.
메서드나 변수를 이미 만들었기 때문에 사용하기 편하다.
배열은 각각의 변수들을 하나로 묶어준 것이다.
똑같은 땅을 어떻게 효율적으로 쓸 수 있을까?
집을 지을 때 같은 평수에 단독주택을 지으면 1개
아파트 같은 다세대 주택을 지으면 여러명이 살 수 있다.
이처럼 배열은 마치 아파드 처럼 같은 공간을 효율적으로 사용하기 위한 방법이다.
이때 아파트가 동 호수가 있는 것처럼 배열도 공간마다 번호를 붙이는데 이를 index라고 한다.
그중에서 하나하나의 변수를 1줄로 붙여놓은 묶음을 1차원 배열이라고 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class Arraytest { public static void main(String[] args) { int no=1, kor=70, eng=55, mat=87; //인스턴스 생성 -> 변수가 있어야한다. //java에서는 배열을 객체로 취급하기 때문에 인스턴스를 생성한다. int [] first = new int[4]; //[숫자]번째 방에 값이 들어간다.(초기화 작업) first[0]=1; first[1]=70; first[2]=55; first[3]=87; //변수는 반복문을 쓸 수 없지만, 배열은 규칙성이 있어서 반복문을 쓸 수 있다. for(int i=0; i<4; i++) { System.out.println(first[i]); } } } | cs |
※ 결과값
1
70
55
87
초기화를 조금 더 간단히 하는 방법은 없을까?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | public class Arraytest { public static void main(String[] args) { int no=1, kor=70, eng=55, mat=87; /* //인스턴스 생성 -> 변수가 있어야한다. //java에서는 배열을 객체로 취급하기 때문에 인스턴스를 생성한다. int [] first = new int[4]; //[숫자]번째 방에 값이 들어간다.(초기화 작업) first[0]=1; first[1]=70; first[2]=55; first[3]=87; */ // 초기화를 조금 더 간단히 한다. //반드시 동시에 선언하자 마자 초기화를 해야한다. //여기서는 new가 생략된다. int [] first = {1, 70, 55, 87}; //int [] second; //second = {2, 68, 44, 32}; 선언하자마자 초기화하지 않았기에 안된다. //변수는 반복문을 쓸 수 없지만, 배열은 규칙성이 있어서 반복문을 쓸 수 있다. for(int i=0; i<4; i++) { System.out.println(first[i]); } } } | cs |
※결과값
1
70
55
87
이처럼 배열 초기화에는 두가지 방법이 있다.
1. 인스턴스를 선언하고 초기화를 한다.
2. 인스턴스를 선언과 동시에 초기화를 한다.
변수처럼 인스턴스를 선언하지 않고 나중에 값을 넣을 수는 없다.
3. 배열로 할 수 있는 대표적인 알고리즘
1) 검색
1. 순차검색 (sequential)
2. 이분검색 (binary)
2) 정렬
*선수알고리즘 : swap 알고리즘
1. 버블정렬
2. 선택정렬
<검색>
어떻게하면 더 빨리 원하는 것을 찾을까?
그 해법은 알고리즘에 있다.
<검색 방법>
1.순차검색(Sequential)
- 처음부터 끝까지 차례대로 찾기
2.이분검색(bynary)
- 전체데이터를 둘로 양분 후 원하는 데이터가 있는지 없는지를 찾고 이를 반복한다.
- 이 이분 검색은 데이터가 정렬되어 있어야 한다는 조건이 있다.
<순차검색(Sequential)>
그럼 배열을 사용해 순차방식방법으로 간단한 검색기능 프로그램을 짜보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | public class SequentialSearch { public static void main(String[] args) throws java.io.IOException { char [] data = {'a' , 'b' , 'c' , 'd' , 'e', 'f', 'g', 'h'}; System.out.println("찾고자하는 문자 입력 : "); //반복을 통해서 하나씩 비교해보기 char search = (char) System.in.read(); //data.length변수는 데이터 수 범위는 데이터 양만큼 지정한다. for(int i=0; i<data.length; i++) { //실제 저장된 데이터를 비교한다. if(search == data[i]) { System.out.println("찾았다."); break; } } } } | cs |
※결과값
찾고자하는 문자 입력 :
d
찾았다.
'못찾았다'를 입력하고 싶으면 어떻게 할까?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | public class SequentialSearch { public static void main(String[] args) throws java.io.IOException { char [] data = {'a' , 'b' , 'c' , 'd' , 'e', 'f', 'g', 'h'}; System.out.println("찾고자하는 문자 입력 : "); //반복을 통해서 하나씩 비교해보기 char search = (char) System.in.read(); //data.length변수는 데이터 수 범위는 데이터 양만큼 지정한다. for(int i=0; i<data.length; i++) { //실제 저장된 데이터를 비교한다. if(search == data[i]) { System.out.println("찾았다."); break; } else { System.out.println("못찾았다."); } } } } | cs |
※결과값
찾고자하는 문자 입력 : ㅣ
ㅣ
못찾았다.
못찾았다.
못찾았다.
못찾았다.
못찾았다.
못찾았다.
못찾았다.
못찾았다.
그런데 '못찾았다'가 계속나온다.
if문이 계속 반복해서 돌기 때문이다.
이럴 때는 flag 기법을 쓴다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | public class SequentialSearch { public static void main(String[] args) throws java.io.IOException { char [] data = {'a' , 'b' , 'c' , 'd' , 'e', 'f', 'g', 'h'}; System.out.println("찾고자하는 문자 입력 : "); //반복을 통해서 하나씩 비교해보기 char search = (char) System.in.read(); //flag 변수를 지정해준다. boolean flag = false; //data.length변수는 데이터 수 범위는 데이터 양만큼 지정한다. for(int i=0; i<data.length; i++) { //실제 저장된 데이터를 비교한다. if(search == data[i]) { System.out.println("찾았다."); break; } else { flag = false; } } if(flag == true) { System.out.println("찾았다."); } else { System.out.println("못찾았다."); } } } | cs |
※ 결과값
찾고자하는 문자 입력 : o
o
못찾았다.
<이분검색(bynary)>
a, b, c, d, e, f, g, h, i
전체 데이터의 중간 위치를 선택한다.
중간 데이터가 찾는 데이터인지 비교(찾으면 다행)
찾고자 하는 데이터가 어느방향인지 선택 (왼, 오)
전체 데이터의 반을 검색하여 비교.
반씩 개수를 줄여나간다.
위의 과정을 반복
<정렬>
그렇다면 '정렬'은 어떻게 할 수 있을까?
방법은 여러가지다. 오름차순, 내림차순...
정렬은 알고리즘의 핵심개념 중의 하나로
방대한 데이터를 처리할 때 매우 중요하다.
보통 알고리즘에서 기초적으로 배우는 정렬은
'버블정렬, 선택정렬, 삽입정렬'이다.
그 중에서 '버블정렬, 선택정렬'을 알아보자.
알고리즘과 정렬은 그림으로 그려가면서 이해해야 한다.
정렬을 알아가기 그 이전에 먼저 알아야만 하는 알고리즘이 있다.
바로 swap 알고리즘 이다.
<swap 알고리즘>
두 개의 값을 교환해보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 | int i = 10, j = 20; System.out.println(i + ", " + j); /* //컴퓨터는 한 번에 하나씩 값을 처리하기 때문에 값을 교환할 수없다. i = j; j = i; System.out.println(i + ", " + j); */ int k; k = i; i = j; j = k; System.out.println(i + " , " + j); | cs |
swap 알고리즘이란
두 개의 값을 교환할 때는 결코 두개의 변수로만 할 수 없으며
반드시 하나의 임시변수가 있어야 함을 말한다.
<버블정렬>
서로 이웃하는 것끼리 비교정렬
내림차순 : 큰 값이 뒤로가고 작은 값이 앞으로
오름차순 : 큰 값이 앞으로 오고 작은 값이 뒤로
아래숫자를 내림차순으로 정리해보자.
앞에 데이터와 뒤에 데이터를
하나씩 비교하여 자리를 바꾸어 준다.
예를 들어
왼 오
6 3 7 5 <첫번째 반복>
↓ ↓ ↓ ↓
3 6 7 5
↓ ↓ ↓ ↓
3 6 7 5
---------------------------
3 6 5 7 <두번째 반복>
↓ ↓ ↓ ↓
3 6 5 7
↓ ↓ ↓ ↓
3 5 6 7
----------------------
3 6 5 7 <세번째 반복>
↓ ↓ ↓ ↓
3 5 6 7
↓ ↓ ↓ ↓
3 5 6 7
------------------------
3 5 6 7 <결과>
데이터의 갯수가 4개일 때 3번 비교해서 1번의 반복이 끝났다.
시간복잡도 = n^2
<데이터 비교횟수 구하기>
비교횟수 = 데이터의 개수 - 1
버블 소트의 이름은 왜 버블 소트일까?
아마도 버블처럼 값을 한 묶음씩 비교해서라고 추측한다.
public class BubbleSort {
public static void main(String[] args){
// TODO 버블정렬
int data[] = {6, 3, 7, 5};
//비교횟수 = 데이터의 개수 -1
for(int row=0; row<data.length-1; row++) {
for(int col=0; col<data.length-1; col++) {
if(data[col]<data[col+1]) {
int temp = data[col];
data[col] = data[col+1];
data[col+1] = temp;
}
}
}
System.out.println("결과 : ");
for(int i=0; i<data.length; i++) {
System.out.print(data[i] + "\t");
}
}
}
※ 결과값
결과 :
7 6 5 3
<선택정렬>
기준을 하나 정하고 비교대상과 비교정렬
기준점이 있으면 기준 이후 혹은 이전의 비교 대상들과 비교를 해서
기준이 되는 자리에 원하는 값을 집어넣는다.
public class SelectionSort {
public static void main(String[] args) {
//TODO 선택정렬
int data[] = {6, 3, 7, 5};
//비교횟수 = 데이터의 개수 -1
for(int row=0; row<data.length-1; row++) {
for(int col=row+1; col<data.length; col++) {
if(data[row]<data[col]) {
int temp = data[row];
data[row] = data[col];
data[col] = temp;
}
}
}
System.out.println("결과 : ");
for(int i=0; i<data.length; i++) {
System.out.print(data[i] + "\t");
}
}
}
※ 결과값
결과 :
7 6 5 3
<이클립스 팁!>
ctrl + space
sysout + ctrl + space = System.out.println();
alt + ↓ or ↑ = 소스코드 한 줄 이동
4. 다차원 배열 (2차원 배열 이상)
일차원 배열을 하나로 합친 것이
이차원 배열이다.
이차원배열과 이차원 배열을 합친 것이 삼차원 배열이다.
행과 열의 위치로
차원 = 어떻게 묶어 나가는가?
1차원 + 1차원 = 2차원
2차원 + 2차원 = 3차원
[]대괄호 개수가 차원을 나타낸다.
public class MultiDimension {
public static void main(String[] args) {
// TODO 다차원 배열
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = {6, 7, 8, 9, 10};
int[] arr3 = {11, 12, 13, 14, 15};
//[]대괄호의 개수가 차원
int[][]arr4 = new int[3][5];
arr4[0][0] = 1;
arr4[0][1] = 2;
arr4[0][2] = 3;
arr4[0][3] = 4;
arr4[0][4] = 5;
arr4[1][0] = 6;
arr4[1][1] = 7;
arr4[1][2] = 8;
arr4[1][3] = 9;
arr4[1][4] = 10;
arr4[2][0] = 11;
arr4[2][1] = 12;
arr4[2][2] = 13;
arr4[2][3] = 14;
arr4[2][4] = 15;
for(int row=0; row<3; row++) {
for(int col=0; col<5; col++) {
System.out.print(arr4[row][col] + "\t");
}
System.out.println();
}
}
}
※ 결과값
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
초기화를 조금 더 편하게 하려면 어떻게 해야할까?
public class MultiDimension {
public static void main(String[] args) {
// TODO 다차원 배열
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = {6, 7, 8, 9, 10};
int[] arr3 = {11, 12, 13, 14, 15};
/*
//[]대괄호의 개수가 차원
int[][]arr4 = new int[3][5];
arr4[0][0] = 1;
arr4[0][1] = 2;
arr4[0][2] = 3;
arr4[0][3] = 4;
arr4[0][4] = 5;
arr4[1][0] = 6;
arr4[1][1] = 7;
arr4[1][2] = 8;
arr4[1][3] = 9;
arr4[1][4] = 10;
arr4[2][0] = 11;
arr4[2][1] = 12;
arr4[2][2] = 13;
arr4[2][3] = 14;
arr4[2][4] = 15;
*/
//다차원 배열은 배열의 수 만금 중괄호로 묶어주어야한다.
//줄바꿈을 해주면 보기가 편하다.
int[][]arr4 = {{1,2,3,4,5},
{6,7,8,9,10},
{11,12,13,14,15}};
for(int row=0; row<3; row++) {
for(int col=0; col<5; col++) {
System.out.print(arr4[row][col] + "\t");
}
System.out.println();
}
}
}
※ 결과값
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
삼차원 배열을 어떻게 해야할까?
삼차원 배열에서 부터는 입체감이 생긴다.
면의 개수가 하나씩 더 생긴다.
public class MultiDimension {
public static void main(String[] args) {
int[][] arr4 = { { 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 11, 12, 13, 14, 15 } };
int[][] arr5 = { { 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 11, 12, 13, 14, 15 } };
// int arr6[][][] = new int[2][3][5];
int[][][] arr6 = { { { 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 11, 12, 13, 14, 15 } },
{ { 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 11, 12, 13, 14, 15 } } };
for (int a = 0; a < 2; a++) {
for (int b = 0; b < 3; b++) {
for (int c = 0; c < 5; c++) {
System.out.print(arr6[a][b][c] + "\t");
}
System.out.println();
}
System.out.println();
}
}
}
※ 결과값
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
<불규칙배열>
각 행마다 열의 길이를 다르게 할 수 있는 배열
불필요한 공간을 줄일 수있다.
그러나 이 방법보다 더 좋은 방법이 나와서
잘 쓰지는 않기 때문에 개념만 알아두고 넘어간다.
char [] name1 = {'홍', '길', '동'};
char [] name2 = {'T', 'o', 'm'};
char [] name3 = {'J', 'o', 'h', 'n', 's', 'o', 'n'};
char [] name4 = {'J', 'a', 'n', 'e'};
//char[][] names = new char[4][7];
char[][] names = new char[4][];
...
names[0] = new char[3];
names[0][0] = '홍';
names[0][1] = '길';
naems[0][2] = '동';
...
names[1] = new char[3];
지금까지 배열 공부를 총 정리하며 신나게 학점을 구해봅시다.
public class Sunjuk_v1 {
public static void main(String[] args) {
// TODO 1차원 배열을 이용한 성적표
// 번호, 국어,영어는 값을 입력함
int[] no = { 1, 2, 3 };
int[] kor = { 98, 76, 85 };
int[] eng = { 90, 55, 73 };
// 총점, 평균, 학년, 순위는 변수선언만 함.
int[] tot = new int[3];
int[] avg = new int[3];
char[] grade = new char[3];
int[] rank = new int[3];
// 총점 구하기
for (int i = 0; i < no.length; i++) {
tot[i] = kor[i] + eng[i];
}
// 평균구하기
for (int i = 0; i < no.length; i++) {
avg[i] = tot[i] / 2;
}
// 학점 구하기
for (int i = 0; i < no.length; i++) {
if (avg[i] >= 90)
grade[i] = 'A';
else if (avg[i] >= 80)
grade[i] = 'B';
else if (avg[i] >= 70)
grade[i] = 'C';
else if (avg[i] >= 60)
grade[i] = 'D';
else
grade[i] = 'F';
}
// 등수 구하기
System.out.println("***성적결과***");
System.out.println("학번\t국어\t영어\t총점\t평균\t학점");
System.out.println("---------------------------------------------");
for (int i = 0; i < no.length; i++) {
System.out.println(no[i] + "\t" + kor[i] + "\t" + eng[i] + "\t"
+ tot[i] + "\t " + avg[i] + "\t" + grade[i]);
}
System.out.println("정렬 후.......");
for (int row = 0; row < no.length - 1; row++) {
for (int col = row + 1; col < no.length; col++) {
if (avg[row] < avg[col]) {
int iTemp = no[row];
no[row] = no[col];
no[col] = iTemp;
iTemp = kor[row];
kor[row] = kor[col];
kor[col] = iTemp;
iTemp = eng[row];
eng[row] = eng[col];
eng[col] = iTemp;
iTemp = tot[row];
tot[row] = tot[col];
tot[col] = iTemp;
iTemp = grade[row];
grade[row] = grade[col];
grade[col] = (char) iTemp;
}
}
}
System.out.println("***성적결과***");
System.out.println("학번\t국어\t영어\t총점\t평균\t학점");
System.out.println("---------------------------------------------");
for (int i = 0; i < no.length; i++) {
System.out.println(
no[i] + "\t" + kor[i] + "\t" + eng[i] + "\t" + tot[i] + "\t " + avg[i] + "\t" + grade[i]);
}
}
}
※결과값
***성적결과***
학번 국어 영어 총점 평균 학점
---------------------------------------------
1 98 90 188 94 A
2 76 55 131 65 D
3 85 73 158 79 C
정렬 후.......
***성적결과***
학번 국어 영어 총점 평균 학점
---------------------------------------------
1 98 90 188 94 A
3 85 73 158 65 C
2 76 55 131 79 D
★ 연습문제 ★
예제에 있는 버블 반복을 한 번씩 줄여본다.
학점구하기에서 등수 구해본다.
어제 만든 학점관리 프로그램을 바꾸어 보자
참고로 배열은 같은 형식만 묶을 수 있다.
public class Sunjuk_v2 {
public static void main(String[] args) {
// TODO 2차원 배열을 이용한 성적표
//배열은 같은 형식 끼리만 묶을 수 있다.
//3행 6열로 데이터를 배열해준다.
int[][] sungjuk = {
{1, 98, 90, 0, 0, 0},
{2, 76, 55, 0, 0, 0},
{3, 85, 73, 0, 0, 0}
};
char[] grade = new char[3];
// 총점 구하기
for (int i = 0; i < 3; i++) {
sungjuk[i][3] = sungjuk[i][1] + sungjuk[i][2];
}
// 평균구하기
for (int i = 0; i < 3; i++) {
sungjuk[i][4] = (sungjuk[i][1] + sungjuk[i][2]) / 2;
}
// 학점 구하기
for (int i = 0; i < 3; i++) {
if (sungjuk[i][4] >= 90)
grade[i] = 'A';
else if (sungjuk[i][4] >= 80)
grade[i] = 'B';
else if (sungjuk[i][4] >= 70)
grade[i] = 'C';
else if (sungjuk[i][4] >= 60)
grade[i] = 'D';
else
grade[i] = 'F';
}
// 등수 구하기
System.out.println("***성적결과***");
System.out.println("학번\t국어\t영어\t총점\t평균\t학점\t순위");
System.out.println("---------------------------------------------");
for (int i = 0; i < sungjuk.length; i++) {
System.out.println(sungjuk[i][0] + "\t" + sungjuk[i][1] + "\t" + sungjuk[i][2] + "\t"
+ sungjuk[i][3] + "\t " + sungjuk[i][4] + "\t" + grade[i] + "\t" + sungjuk[i][5]);
}
System.out.println("정렬 후.......");
//2차원 배열은 값을 바꾸지 않고 행의 주소를 바꾸면 된다.
for (int row = 0; row < sungjuk.length-1; row++) {
for (int col = row+1; col < sungjuk.length; col++) {
if (sungjuk[row][4] < sungjuk[col][4]) {
int[] rowTemp = sungjuk[row];
sungjuk[row] = sungjuk[col];
sungjuk[col] = rowTemp;
char gradeTemp = grade[row];
grade[row] = grade[col];
grade[col] = gradeTemp;
}
}
}
System.out.println("***성적결과***");
System.out.println("학번\t국어\t영어\t총점\t평균\t학점\t순위");
System.out.println("---------------------------------------------");
for (int i = 0; i < sungjuk.length; i++) {
System.out.println(sungjuk[i][0] + "\t" + sungjuk[i][1] + "\t" + sungjuk[i][2] + "\t"
+ sungjuk[i][3] + "\t " + sungjuk[i][4] + "\t" + grade[i] + "\t" + sungjuk[i][5]);
}
}//main end
}//class end
※ 결과값
***성적결과***
학번 국어 영어 총점 평균 학점 순위
---------------------------------------------
1 98 90 188 94 A 0
2 76 55 131 65 D 0
3 85 73 158 79 C 0
정렬 후.......
***성적결과***
학번 국어 영어 총점 평균 학점 순위
---------------------------------------------
1 98 90 188 94 A 0
3 85 73 158 79 C 0
2 76 55 131 65 D 0
2차원 배열은 배열명.length를 했을 때 행의 개수 만큼 돈다.
2차원 배열 부터는 비교 할 때 값을 바꿀 필요 없이 행의주소만 바꾸면된다.
배열에서는 문자열을 잘 쓰지 않는다.
문자열은 일일히 주소값을 저장해서불러오기 불편하기 때문이다.
그래서 배열은 숫자값만 이용한다.
그러면 어떻게 해야할까?
자바에서는 개발자가 문자열을 쓰기편하도록
문자열 전용 클래스를 만들었는데 바로 그것이 string이다.
6. String
문자나 문자열은 배열처리하지말고 String 클래스를 이용한다.
string 클래스는 배열을 쉽게 쓸 수 있도록 클래스로 만든 하나의 1차원 배열 클래스이다
모든 클래스는 반드시 인스턴스가 있어야 한다.
그렇기 때문에 String클래스도 인스터스를 선언한다.
그럼 String클래스를 배열로 만들 수는 없을까?
결론적으로 할 수 있다.
다만, String 클래스가 원래 배열을 클래스로 만든 것이기 때문에
자바에서는 개발자가 복잡하지 않도록 String클래스를
다른 배열과 마찬가지 형식으로 만들 수 있도록 했다.
public class StringTest {
public static void main(String[] args) {
// TODO String클래스의 기본 사용법
//모든 클래스는 반드시 인스턴스가 있어야 한다.
String str = new String();
str= "홍길동";
System.out.println(str);
//클래스이기 때문에 이런 선언도 가능하다.
String str2 = new String("임꺽정");
System.out.println(str2);
//바로 초기화도 가능하다.
String str3 = "김유신";
System.out.println(str3);
//string 클래스를 배열로 만들기
String[] names = new String[3];
names[0] = "홍길동";
names[1] = "임꺽정";
names[2] = "김유신";
for(int i=0; i <names.length; i++) {
System.out.println(names[i]);
}
}
}
※ 결과값
홍길동
임꺽정
김유신
홍길동
임꺽정
김유신
String 클래스의 자세한 설명과 메소드는 Java API를 참조하자.
http://docs.oracle.com/javase/9/docs/api/index.html?overview-summary.html
(String 메서드와 사용법 API에서 어떤 메서드인지, 용례가 무엇인지 정리해보자)
그렇다면 String 클래스의 특징은 무엇일까?
1) 자바는 문자열을 객체로 취급한다.
객체로 만들어져있다는 것은 클래스로 만들어져 있다는 이야기고
클래스로 만들어져 있다는 것은 변수나 메소드를 쓸 수 있다는 것이다.
문자열을 변수로 담아서 쓸 수도 있고, 문자열 자체에서 . 을 찍어 쓸 수도 있다.
String class 가 제공하는 메소드를 예제와 함께 살펴보자
public class StringTest2 {
public static void main(String[] args) {
// TODO String클래스가 제공하는 기능들
String str1 = "java";
String str2 = "java";
//.equauls 는 String에서 값을 비교하는 메서드이다.
System.out.println(str1.equals(str2));
//자바는 문자열을 객체로 취급하기 때문에 . 으로 변수의 값을 가져올 수 있다.
System.out.println("java is mylife".equals(str2));
String str3 = "java is beautiful";
String str4 = "java";
//.compareTo는 앞의 문자열과 뒤의 문자열을 아스키코드값 숫자로 비교한다.
//.compareTo는 리턴값이 세가지 있다. 양수, 0, 음수
//음수가 나올 때는 뒤의 문자열이 크다는이야기다.
//str3과 str4의 문자열이 달라지는 지점에서 아스키 코드의 차이를 비교해서 뺀 값을 저장한다.
//.compareTo는 문자를 구별하는 게임에 넣어주면 재밌다.
System.out.println(str3.compareTo(str4));
//.charAt지정된 위치에서 한 글자를 추출하는 메서드
//3번째 위치에 한 글자를 가져오겠다.
System.out.println(str3.charAt(3));
//.indexOf 문자, 문자열이 왼쪽부터 어느 위치에 있는지 찾아준다.
//str3 문자열에서 is라는 문자가 어느 위치에 있는가?
System.out.println(str3.indexOf("is"));
System.out.println(str3.indexOf("a"));
//.lastIndexOf 문자, 문자열이 가장 오른쪽 부터 어느위치에 있는지 순번은 왼쪽부터 센다.
System.out.println(str3.lastIndexOf("a"));
//찾고자 하는 단어가 없다면 -1이 나온다.
//.indexOf는 주로 검색용도로 해당 단어가 있는지 없는지를 찾을 때 더 많이 나온다. 예)순차검색
System.out.println(str3.lastIndexOf("love"));
//.substring(시작위치, 끝위치) 은 문자의 일부분을 추출할 때 사용
//첫번째 시작 위치는 0부터 시작하지만, 2번째 끝위치는 1부터 시작한다. 그래서 i만 나온다.
System.out.println(str3.substring(5, 6));
//이번에는 is가 모두 나온다.
System.out.println(str3.substring(5, 7));
//특정위치 구간에 있는 문자를 추출할 때 사용
System.out.println(str3.substring(5));
}
}
※ 결과값
true
false
13
a
5
1
10
-1
i
is
2) java.lang이라는 폴더에 있는 클래스이다.
3) 동일한 인스턴스를 중복해서 만들지 않는다.
- 메모리 스캔으로 똑같은 값을 저장하지 않고 주소를 복사한다.
public class StringTest3 {
public static void main(String[] args) {
// TODO String클래스의 주요 특징
//new를 쓰지 않으면 String 클래스는 중복값을 체크해 인스턴스를 만들지 않고 주소를 복사한다.
String str1 = "java";
String str2 = "java";
//값이 같은지 체크
System.out.println(str1.equals(str2));
//주소가 같은지 체크
System.out.println(str1 == str2);
//new를 쓰면 강제로 인스턴스가 만들어진다.
String str3 = new String("java");
System.out.println(str3.equals(str2));
System.out.println(str3 == str2);
}
}
※ 결과값
true
true
true
false
4) 절대 수정 불가능 하다. (고칠 수 없다. 덮어 씌우는 것도 안된다.)
수정을 하면 인스턴스를 새로 만들고 기존의 값은 쓰레기 값이 된다.
public class StringTest3 {
public static void main(String[] args) {
// TODO String클래스의 주요 특징
/*
//new를 쓰지 않으면 String 클래스는 중복값을 체크해 인스턴스를 만들지 않고 주소를 복사한다.
String str1 = "java";
String str2 = "java";
//값이 같은지 체크
System.out.println(str1.equals(str2));
//주소가 같은지 체크
System.out.println(str1 == str2);
//new를 쓰면 강제로 인스턴스가 만들어진다.
String str3 = new String("java");
System.out.println(str3.equals(str2));
System.out.println(str3 == str2);
*/
//String 클래스는 다른 문자열로 바꿔쓰면 인스턴스를 새로 만든다.
//그러므로 기존 문자열은 쓰레기 값이 된다.
String str1 = "javu";
str1 = "java";
//.concat 앞에 있는 문자열과 뒤에 있는 문자열을 연결해주는 메소드
String str2 = str1.concat(" is number one");
System.out.println(str2);
System.out.println(str1 == str2);
}
}
※ 결과값
java is number one
false
동일한 인스턴스를 중복해서 만들지 않고 수정이
불가하다는 것은 메모리를 알뜰하게 쓴다는 면에서 좋다.
하지만, 인스턴스를 중복해서 만들지 않으려고 하기 때문에
메모리 스캔을 해야해서 리소스가 많이 잡아먹고,
코딩을 하다보면 수정할 일이 생길 때가 있다.
이런 String클래스의 불편함을 해소하기위 해 나온 클래스가 있다.
5. StringBuffer, StringBuilder
- 수정이 가능하다. 문자열을 자주 수정되는 경우는 StringBuffer, StringBuilder를 사용하면 된다.
- 특히 StringBuffer는 예전부터 있었기 때문에 호환성이 더 좋다.
- 사용방법은 String과 같으나 사용할 수 있는 메서드가 String 보다는 제한적이다.
- 기본 데이터 타입은 캐스팅이 되지만 클래스는 캐스팅이 될 수 없다.
public class StringTest3 {
public static void main(String[] args) {
// TODO String클래스의 주요 특징
//String 클래스는 다른 문자열로 바꿔쓰면 인스턴스를 새로 만든다.
//그러므로 기존 문자열은 쓰레기 값이 된다.
String str1 = "javu";
str1 = "java";
//.concat() 앞에 있는 문자열과 뒤에 있는 문자열을 연결해주는 메소드
String str2 = str1.concat(" is number one");
System.out.println(str2);
System.out.println(str1 == str2);
//기본 데이터 타입은 캐스팅이 되지만 클래스는 캐스팅이 될 수 없기 때문에 new로 인스턴스를 생성한다.
StringBuffer sb1 = new StringBuffer("java");
//.append()앞에 있는 문자열과 뒤에 있는 문자열을 연결해주는 메소드 (.concat 과 같음)
StringBuffer sb2 = sb1.append("is number one" );
//주소가 같다고 나오기 때문에 수정이 된 것이 증명됨.
System.out.println(sb1 == sb2);
}
}
※ 결과값
java is number one
false
true
java.util.Scanner scan = new java.util.Scanner();
입력을 받을 때 편하게 해주는 장치이다.
여기서 Scanner는 껍데기이다.
어떤 장치를 넣을 때 편하게 해주는 매개이다. (Scanner에 입력해야한다.)
키보드에서 입력을 할 때 편한 장치를 해줘야한다.
System.in 이라는 참조변수가 키보드의 주소값이다.
System.out 은 모니터의 주소값
1차원, 2차원 배열을 이름과 점수를 입력받아 출력하는 프로그램을 만들어보자.
public class ScannerTest {
public static void main(String[] args) {
// TODO Scanner 클래스의 간단 사용법
//java.lang. = 가장 기본적인 폴더. 생략해도 된다.
//이외에 다른 폴더는 반드시 이름을 써야한다.
java.util.Scanner scan = new java.util.Scanner(System.in);
System.out.print("이름입력");
String name = scan.next();
System.out.println("당신의 이름은 " + name + " 이다.");
//java.lang. = 가장 기본적인 폴더. 생략해도 된다.
System.out.println("숫자를 마음껏 입력 : ");
int num = scan.nextInt();
System.out.println("입력한 숫자 : " + num);
System.out.println("실수 입력 : ");
double dnum = scan.nextDouble();
System.out.println("입력한 실수 : " + dnum);
}
}
※ 결과값
이름입력 마봉춘
당신의 이름은 마봉춘 이다.
숫자를 마음껏 입력 :
0416
입력한 숫자 : 416
실수 입력 :
503.65
입력한 실수 : 503.65
7. 명령행인자 (Command Line Argument)
- 명령행 : 사용자가 입력 할 수 있는 상태
- 인자 : 메소드가 호출 할 때 넘어가는 실제값
- 명령행 인자 : 메소드를 호출할 때 값을 넘겨주는 방법을 코드가 아닌 실행 할 때 하겠다.
사용자가 원하는 Dos 에서 값을 입력하면
단순히 프로그램만 실행하는 것이 아니라 인자값도 같이 넘겨준다.
그렇다면 이런 명령행인자는 인자값을 넘길 때
실인자를 받아 줄 수 있는 매개변수는 어디에 있을까?
main 메서드의 args가 실행할 때 덤으로 넘어오는 명령행인자를 받아와서 처리한다.
ars는 String 배열로 되어있어 String[] args 가 된다.
public class CmdLineTest {
public static void main(String[] args) {
//TODO 명령행인자 테스트
//첫번째 문자 출력
//이클립스에서는 실행하기 복잡하기 때문에 Dos 창에서 실행해보자.
System.out.println(args[0]);
}
}
이클립스에서는 실행하기 복잡하기 때문에 Dos 창에서 실행해보자.
cmd 창에서 java 명령어를 이용해서 명령행 인자를 테스트하면,
인자를 두 개를 입력하는 방법은 없을까?
public class CmdLineTest {
public static void main(String[] args) {
//TODO 명령행인자 테스트
//첫번째 문자 출력
//이클립스에서는 실행하기 복잡하기 때문에 Dos 창에서 실행해보자.
System.out.println(args[0]);
System.out.println(args[1]);
}
}
값을 주지 않으면 에러가 나지만, 인자를 두개를 입력하면 에러가 나지 않고 인자가 출력된다.
인자의 구분은 공백으로 한다.
그런데 내가 원하는 만큼 인자의 값을 입력하는 방법은 없을까?
public class CmdLineTest {
public static void main(String[] args) {
//TODO 명령행인자 테스트
//첫번째 문자 출력
//이클립스에서는 실행하기 복잡하기 때문에 Dos 창에서 실행해보자.
//System.out.println(args[0]);
//System.out.println(args[1]);
for(int i=0; i<args.length;i++) {
System.out.println(args[i]);
}
}
}
이렇게 명령행인자는 프로그램이 처음 실행될 때 한 번 입력을 받아 메인 메소드에 전달한다.
윈도우에서 실행할 때는 거의 해당이 없지만 도스에서는 해당이 된다.
이런 기능이 있다는 것을 알아두자.
//void : 리턴값이 없다. (가상머신이 main찾는데 가상머신에게 리턴하지 않는다.)
//main 메서드도 시스템이 찾는 콜백메서드이다.
//(String[] args)는 명령행 인자를 위한 매개변수이다.
public static void main(String[] args)
<참고>
배열에서는 길이를 알아낼 때 length라는 변수를 썼지만,
String클래스는 .length()라는 메소드를 사용한다.
연산자를 이용해 데이터 암호화 및 복호화를 해보자.
public class Encode {
public static void main(String[] args) {
//TODO xor연산자를 이용한 데이터 암호화 및 복호화
String original = "X맨은 홍길동이다.";
//key값과 original을 일대일로 대응시켜 암호화한다.
//key값이 모자르면 다시 처음으로 돌아와 비교할 수 있도록 한다.
String key = "D$@?ab10";
String encoding = " ";
int keyCnt = 0;
//문자 2진수는 정수형으로 바꿀 수 있지만 문자열은 바꿀 수 없다.
//그러므로 배열로 하나씩 문자를 뽑아 암호로 바꾸어야 한다.
//배열에서는 길이를 알아낼 때 length라는 변수를 썼지만,
//String클래스는 .length()라는 메소드를 사용한다.
for(int i=0; i<original.length(); i++) {
//글자 하나씩 비교하여 암호화하는 작업을 계속 누적하여 연산하겠다.
//문자로 바꿔서 캐스팅해준다.
//key값이 original값과 길이가 다르기 때문에 반복을 따로 돌린다.
encoding += (char)(original.charAt(i) ^ key.charAt(keyCnt));
keyCnt++;
//key는 encoding의 반복이 끝나도 초기화해서 계속 반복해줘야하기 때문에
if(keyCnt == key.length()) {
keyCnt = 0;
}
}
System.out.println("암호화 : " + encoding);
//복호화는 과제
}
}
※결과값
암호화 : 만윀혬깚돨을늠
★ 연습문제 ★
간단한 개인정보관리 프로그램 PMS 을 만들어보자.
예)
PhoneBook
---------
데이터 준비(배열)
홍길동, 111-1111, 서울시 종로구
임꺽정, 222-1111, 서울시 강남구
신돌석, 333-1111, 서울시 노원구
java PhoneBook 홍길동
전번 : 111-1111
주소 : 서울시 종로구
StringBuffur (StringBuilder)
- 반드시 new로 인스턴스를 생성
- 수정가능
- StringBuffur에서는 .eqals(), == 둘다 주소를 비교.
- String 에서는 .eqals()는 주소비교, ==는 값을 비교.
(원래는 둘 다 주소를 비교하는 기능이지만 편의상 ==을 값 비교로 함.)
- .compareTo 만 값을 비교할 때 사용가능.
String 클래스에서 값 비교하기
String 입력 = abc
입력 == "abc" // 같다가 아니다. 주소값비교이다.
입력.equals("abc") //값을 비교해줄 때는 .equals 이다.
'개발 > Java' 카테고리의 다른 글
[java] 클래스 (Class) part.3 : 상속 (Inheritance ) (0) | 2017.10.24 |
---|---|
[java] 클래스 (Class) part.2 (0) | 2017.10.24 |
[java] 클래스 (Class) part.1 (0) | 2017.10.18 |
[java] 제어문(Control Statement) : 조건문과 반복문 (0) | 2017.10.18 |
[java] Dos에서 Java 컴파일 하기 (0) | 2017.10.18 |