이 자바의 정석을 읽으면서 공부한 내용을 정리하며 기록하는 글이고
주관적인 생각이 들어갈 수 있습니다.
잘못된 내용이나 피드백 및 생각 공유는 언제든 환영입니다.
댓글로 남겨주시면 확인 후 수정하겠습니다.
1. 배열
배열이란 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것이다.
배열을 선언하는 방법은 타입[ ] 변수이름; 으로 선언한다.
그리고 배열을 생성해야 한다. 그 방법은 변수이름 = new 타입[길이];로 생성한다.
아래를 예시로 들자면 이렇다.
int[] score; //배열을 선언
score = new int[5]; //int 타입의 값 5개를 저장할 수 있는 배열 생성
생성된 배열의 각 저장공간을 '배열의 요소'라고 한다.
인덱스는 배열의 요소마다 붙여진 일련번호로 각 요소를 구별하는 데에 사용한다.
배열이름[인덱스]의 형식을 배열의 요소에 접근한다.
인덱스의 범위는 0부터 배열길이-1까지이다.(0부터 시작한다.)
예를 들어 위의 score 변수에 5개의 저장공간을 가지는배열을 선언했는데
처음부터 0~4까지의 인덱스를 가지고 있는 것이다.
위와 같이 길이가 5인 배열은 0~4의 인덱스를 가지고 있다고 했는데
인덱스5와 같은 범위를 벗어나는 인덱스를 사용하면 error가 발생한다.
그 error는 ArrayIndexOutBoundsException이다.
배열의 길이는 int범위의 양이 정수이어야 한다.(0도 포함)
또한 배열이름.length를 사용 시에는 그 배열의 길이의 값을 얻을 수 있다.
아래와 같이 사용된다.
int [] iArr = {100, 95, 80, 70, 60};
//배열의 요소를 순서대로 하나씩 출력
for(int i = 0; i<iArr.length;i++){
System.out.printf("iArr[%d] : %d\t",i,iArr[i]);
}
배열의 길이를 변경하려면 더 큰 배열을 새로 생성 혹은 기존의 배열의 내용을
새로운 배열에 복사하는 것인데 이러한 작업은 비용이 많이 들기 때문에
처음부터 배열의 길이를 넉넉히 잡는 게 좋다.
배열을 생성과 선언을 해줬다면 그 안에 값을 넣어주는 초기화 작업이 있다.
int[] score = new int[5];
score[0] = 50;
score[1] = 60;
score[2] = 70;
score[3] = 80;
score[4] = 90;
배열의 값이 규칙적이고 배열의 길이가 큰 경우에는 for문을 사용하는 게 좋다.
//for문으로 배열의 모든 요소를 출력한다
for(int i=0;i<score.length;i++){
score[i] = 10*i+50;
}
또한 선언과 생성을 동시에 한 경우엔 new int[ ]를 써야 하는 것을 생략할 수 있다.
int [ ] score = {50, 60, 70, 80}; 처럼 하면 그 안에 있는 값을 기준으로 길이가 결정된다.
하지만 선언과 생성을 따로 한 경우에는 생략할 수 없다.
배열을 출력할 때에는 for문을 사용하면 된다.
int [] iArr = {100, 95, 80, 70, 60};
//배열의 요소를 순서대로 하나씩 출력
for(int i = 0; i<iArr.length;i++){
System.out.printf("iArr[%d] : %d\t",i,iArr[i]);
}
더 간단한 방법은 Arrays.toString(배열이름)메서드를 사용하는 것이다.
위와 같은 배열이 선언되고 생성되었을 때 아래처럼 사용한다.
System.out.println(Arrays.toString(iArr));
배열을 복사하는 방법보다 배열을 처음부터 크게 생성하는 게 좋다.
배열의 복사하는 방법으로는 두 가지 방법이 있다.
for문을 이용하는 것과 System.arraycopy()를 이용하는 방법이 있다.
for문부터 알아보자.기존 배열에서 크기를 크게 잡고 크게 잡은 배열에 for문으로
기존 배열 값을 대입한 후기존 배열 주소 값에 더 크게 만든 배열 주소 값을 넣어준다.
//배열 arr에 1~5를 저장한다.
for(int i=0; i<arr.length; i++){
arr[i]=i+1;
}
System.out.println("[변경전]");
System.out.println("arr.length : " + arr.length);
for(int i=0;i<arr.length;i++){
System.out.println("arr["+i+"] : " + arr[i]);
}
int[] mp = new int[arr.length*2];
//배열 arr에 저장된 값들을 배열 tmp에 복사한다.
for(int i=0; i<arr.length; i++){
mp[i] = arr[i];
}
arr = mp; //mp에 저장 후 arr에 저장 주소 값을 저장하는 것 같은 주소를 씀
System.out.println("[변경후]");
System.out.println("arr.length : " + arr.length);
for(int i=0;i<arr.length;i++){
System.out.println("arr["+i+"] : " + arr[i]);
}
System.arraycopy()를 이용한 방법으로는지정된 범위의 값들을 한 번에 통째로 복사한다.
배열의 복사는 for문보다 System.arraycopy()를 사용하는 것이 효율적이다.
System.arraycopy(num, 0, newNum, 0, num.length);
//num의 0번째 인덱스부터 끝까지를 newNum 0번째 인덱스부터 끝까지에
//길이 num.length만큼 복사한다.
또한 배열을 활용할 수 있는 방법은 많다. 여러 가지를 알아 보자
1. 총합과 평균 : 배열의 모든 요소를 더해서 총합과 평균을 구한다.
int sum=0;//총점을 저장하기 위한 변수
float average = 0f;//평균을 저장하기 위한 변수
score = new int[]{100, 88, 100, 100, 90};
//다른 코드에서 score를 선언했기에 int를 안 붙힘
for(int i= 0; i<score.length; i++){
sum += score[i];
}
average = sum / (float)score.length; //계산결과를 float형으로 얻기 위해 형변환
System.out.println("총점 : " + sum);
System.out.println("평균 : " + average);
2. 최대값과 최소값 : 배열의 요소 중에서 제일 큰 값과 제일 작은 값을 찾는다.
score = new int[]{79, 88, 91, 33, 100, 55, 95};
int max = score[0]; //배열의 첫 번째 값으로 최대값을 초기화한다.
int min = score[0]; //배열의 첫 번째 값으로 최소값을 초기화한다.
for(int i=1; i<score.length;i++){
if(score[i]>max){
max = score[i];
} else if(score[i]<min){
min = score[i];
}
}//end for
System.out.println("최대값 : " + max);
System.out.println("최소값 : " + min);
3. 섞기 : 배열의 요소 중에서 제일 큰 값과 제일 작은 값을 찾는다.
int[] numArr = new int[10];
for(int i=0;i<numArr.length;i++){
numArr[i] = i; //배열을 0~9의 숫자로 초기화한다.
System.out.print(numArr[i]);
}
System.out.println();
for(int i=0;i<100;i++){
int n = (int) (Math.random()*10); //0~9까지의 한 값을 임의로 얻는다.
tmp = numArr[0]; //다른 코드에서 tmp를 선언한 상태 선언이 안 되어 있으면 선언을 해줘야 한다.
numArr[0] = numArr[n];
numArr[n] = tmp;
}
for(int i=0; i<numArr.length; i++){
System.out.print(numArr[i]);
}
4. 임의의 값으로 배열 채우기 : 연속 또는 불연속적인 값들로 배열을 초기화 한다.
int[] ball = new int[45]; //45개의 정수 값을 지정하기 위한 배열 생성
//배열의 각 요소에 1~45의 값을 저장한다.
for(int i=0;i<ball.length;i++){
ball[i]=i+1; //ball[0]에 1이 저장된다.
}
int temp = 0; //두 값을 바꾸는데 사용할 임시변수.
int j = 0; // 임의의 값을 얻어서 저장할 변수
// 배열의 i번째 요소와 임의의 요소에 저장된 값을 서로 바꿔서 값을 섞는다.
// 0번째부터 5번재 요소까지 모두 6개만 바꾼다.
for(int i=0;i<6;i++){
j = (int)(Math.random()*45);//0부터 44범위의 임의의 값을 얻는다.
temp = ball[i];
ball[i] = ball[j]; //ball[i]와 ball[j]의 값을 서로 바꾼다.
ball[j] = temp;
}
5. 정렬하기 : 오름차순, 내림차순으로 배열을 정렬
int[] numArr = new int[10];
for(int i=0; i<numArr.length;i++){
System.out.print(numArr[i]=(int)(Math.random()*10));
}
System.out.println();
for(int i=0; i < numArr.length-1;i++){
boolean changed = false; //자리바꿈이 발생했는지를 체크한다.
for(int j=0; j <numArr.length-1-i; j++){
if(numArr[j] > numArr[j+1]){ //옆의 값이 작으면 서로 바뀐다.
/*int*/ temp = numArr[j];
numArr[j] = numArr[j+1];
numArr[j+1] = temp;
changed = true;
}
}//end for
if (!changed) break; //자리 바꿈이 없으면 반복문을 벗어난다.
for(int k =0; k<numArr.length; k++){
System.out.print(numArr[k]); //정렬된 결과를 출력한다.
}
System.out.println();
}
6. 빈도수 구하기 : 배열에 어떤 값이 몇 개 저장되어 있는지 세어서 보여준다.
int[] numArr = new int[10];
int[] counter = new int[10];
for(int i=0; i<numArr.length; i++){
numArr[i] = (int)(Math.random()*10);//0~9의 임의의 수를 배열에 저장
System.out.print(numArr[i]);
}
System.out.println();
for(int i=0;i<numArr.length;i++){
counter[numArr[i]]++;
}
for(int i=0; i < counter.length; i++ ){
System.out.println(i +"의 개수 :"+ counter[i]);
}
2. String 배열
String 배열도 int 배열의 선언과 생성 방법은 다르지 않다.
String[] name = new String[3]; //3개의 문자열을 담을 수 있는 배열을 생성한다.
String 배열도 int 배열과 동일한 방법으로 초기화한다.
String[] name = new String[3];
name[0] = "Kim";
name[1] = "Park";
name[2] = "Yi";
생성, 선언, 초기화, 출력하는 예시로 알아보자
String[] names = {"Kim", "Park", "Yi"};
for (int i = 0; i < names.length; i++) {
System.out.println("names[" + i +"] : " + names[i]);
}
String tmp1 = names[2]; //배열 names의 세 번째 요소를 tmp1에 저장
System.out.println("tmp1 : " + tmp1);
names[0] = "Yu";// 배열 names의 첫 번째 요소를 "Yu"로 변경
for(String str : names){ //향상된 for문
System.out.println(str);
}
자바에서 char배열에 여러 기능을 추가하여 확장한 것이 String배열이기 때문에
String배열로 문자열을 처리해야 한다.
String에서는 주요 메서드가 있다.
그 중에 대표적인 메서드는
char charAt(int index) : 문자열에서 해당 인덱스에 위치하는 문자를 반환한다.
String str = "ABCDE";
char ch = str.charAt(3); //01234순이니깐 인덱스의3인 'D'가 ch에 저장
int length() : 문자열의 길이를 반환한다.
String str = "ABCDE";
int length = str.length() //str의 길이의 값 5를 length에 저장
String substring(int from, int to) : 문자열에서 from~(to - 1)의 인덱스에 있는 문자열을 반환한다.
String str = "ABCDE";//인덱스는 0부터 시작
String tmp = str.substring(0,3);//인덱스 0부터 2까지의 문자열을 tmp에 저장한다.
//0~3이 아니라 0~2이다. 이유는 문자열의 마지막에는 항상 끝 문자가 있다.
//0~3에서 3에 해당하는 인덱스에는 끝 문자가 있기 때문이다.
System.out.println(tmp); //ABC가 출력된다.
boolean equals (Object obj) : 문자열 내용이 obj와 같은 지 확인한다.
String str = "ABCDE";
boolean compare = str.equals("ABCDE"); // str의 문자열과 "ABCDE"의 문자열을 비교해
// 맞으면 ture, 틀리면 false를 compare에 저장
System.out.println(compare);//true 출력
char[ ] toCharArray() : 문자열을 문자배열(char[ ])로 변환해서 반환한다.
String str = "ABCDE";//문자열 저장
char[] tmp = str.toCharArray();//문자열을 문자배열로 변환해 tmp에 저장
System.out.println(tmp[1]);//인덱스1에 맞는 'B'출력
3. 다차원 배열
2차원 배열을 선언하는 법은 아래와 같다.
int[][] score = new int[4][3]; //4행 3열의 2차원 배열을 생성
2차원 배열의 인덱스 뿐만 아니라 인덱스는 0부터 시작하기 때문에
4행은 0,1,2,3의 인덱스로 이루어져 있고 3행은 0,1,2의 인덱스로 이루어져 있다.
2차원 배열을 선언했으니 값을 초기화를 해야 된다.
int[][] score = new int[4][3];//4행 3열 2차원 배열 생성
score = new int[][]{
{1,2,3},
{4,5,6},
{7,8,9},
{10,11,12}
};
//4행 3열에 맞춰서 값 초기화
//new int[][]를 넣어줘야 한다. 생성과 동시에 초기화할 때에는 new int[][] 생략 가능
System.out.println(score[1][2]); //2행 3열의 값인 6이 출력
여기서 score의 length값은 얼마일까?
2차원 배열은 1차원 배열을 여러 개로 묶은 것이다.
1차원 배열의 개수가 즉 길이의 값이라는 것이다. 즉 4가 나온다.
그 안의 1차원 배열의 길이는 3이다.
그래서 아래와 같이 score의 배열에 값을 전부 10으로 초기화할 수 있다.
for(int i = 0; i < score.length; i++){
for(int j = 0; j < score[i].length; j++){
score[i][j]= 10;
}
}
가변 배열 같은 경우에는 위에서 말했 듯이 2차원 배열은 1차원 배열을 여러개로 묶은 것이다.
하지만 이 1차원 배열들이 길이가 각각 다를 수 있다. 이러한 경우가 가변 배열이다.
아래와 같이 표현할 수 있다.
int[][] score = [4][]; //오른쪽 열을 비워둔다.
score[0] = new int[3]; //열생성 인덱스0 즉 1행의 열은 3열이다.
score[1] = new int[4]; //열생성 인덱스1 즉 2행의 열은 4열이다.
score[2] = new int[5]; //열생성 인덱스2 즉 3행의 열은 5열이다.
score[3] = new int[6]; //열생성 인덱스3 즉 4행의 열은 6열이다.