1. 배열(array)

1.1 배열(array)이란?

같은 타입의 여러 변수를 하나의 묶음으로 다루는 것
int score1, score2, score3, score4, score5;
배열 선언시 int[] score = new int[5] // 5개의 int값 저장 가능

선언방법 : 타입[]변수이름;

1.2 배열의 선언과 생성

배열을 선언한 다음에는 배열을 생성 해야한다. 배열을 선언하는 것은 단지 생성된 배열을 다루기 위한 참조변수를 위한 공간이 만들어질 뿐이고, 배열을 생성해야만 비로소 값을 저장할 수 있는 공간이 만들어지는 것이다.

타입[] 변수이름; //배열을 선언(배열을 다루기 위한 참조변수 선언)
변수이름 = new 타입[길이]; // 배열을 생성(실제 저장공간을 생성)

타입[] 변수이름 = new 타입[길이] // 배열의 선언과 생성을 동시에
int[] score = new int[5] // 길이가 5인 int 배열

1.3 배열의 길이와 인덱스

생성된 배열의 각 저장공간을 '배열의 요소(element)'라고 하며, '배열이름[인덱스]'의 형식으로 배열의 요소에 접근한다. 인덱스(index)는 배열의 요소마다 붙여진 일련번호로 각 요소를 구별하는데 사용된다.

인덱스는 1이 아닌 0부터 시작

인덱스(index)의 범위는 0부터 '배열길이-1'까지

배열의 장점은 index로 상수 대신 변수나 수식도 사용할 수 있다는 것이다. 그래서 for문을 이용해서 간단히 할 수 있다. for문의 제어변수 I는 배열의 index로 사용하기에 딱 알맞아서, 배열을 다룰때 for문은 거의 필수적이다.

주의점 : index의 범위를 벗어난 값을 index로 사용하지 않아야 한다.

길이가 0인 배열도 생성이 가능하다.
배열의 길이는 int범위의 양의 정수(0도 포함)이어야 한다.
배열이름.length : 배열의 길이에 대한 정보를 준다.

int[] arr = new int[5]; // 길이가 5인 int배열
int tmp = arr.length; // arr.length의 값은 5이고 tmp에 5가 저장된다.
배열은 한번 생성하면 길이를 변경할 수 없기 때문에, 이미 생선된 배열의 길이는 변하지 않는다.

for (int i = 0; i < score.length; i++) {
}
배열의 길이를 직접 적어주는 것보다 '배열이름.length'를 사용하는 것이 코드의 관리가 쉽고 에러가 발생할 확률이 적어진다.

배열의 길이를 변경하는 방법 :
1. 더 큰 배열을 새로 생선한다.
2. 기존 배열의 내용을 새로운 배열에 복사한다.
기존의 2배정도의 길이로 생성하는 것이 좋다.

1.4 배열의 초기화

배열을 생성과 동시에 자동적으로 자신의 타입에 해당하는 기본값으로 초기화 되지만, 원하는 값을 저장하려면 각 요소마다 값을 지정해줘야 한다.
int[] score = new int[] {1,2,3,4,5};
int[] score = {1,2,3,4,5}; // new int[]를 생략할 수 있다.

int[] iArr = {100, 93, 24, 25, 26};
System.out.println(Arrays.toString(iArr)); /[I@123141
출력값은 '타입@주소'형식으로 출력.
I는 1차원 int배열이라는 의미이고, '@'뒤에 나오는 16진수는 배열의 주소인데 실제 주소는 아니고 내부 주소이다.

예외적으로 char배열은 println메서드로 출력하면 각 요소가 구분자 없이 그대로 출력된다. 이것은 println메서드가 char 배열일 때만 이렇게 동작하도록 작성되서이다.

1.5 배열의 복사

int[] arr = new int[5];
int[] tmp = new int[arr.length*2]; // 기존 배열보다 길이가 2배인 배열
for(int i = 0; i < arr.lengthl i++)
tmp[i] = arr[i]; // arr[i]의 값을 tmp[i]에 저장
arr = tmp; // 참조변수 arr이 새로운 배열을 가리키게 한다.
너무 크게 잡으면 낭비 됨으로, 기존의 2배 정도의 길이로 배열을 생성하는게 좋다.

System.arraycopy()를 이용한 배열의 복사
for문 대신 System클래스의 arraycopy()를 사용하면 보다 간단하고 빠르게 배열을 복사할 수 있다. for문은 배열의 요소에 하나하나 접근해서 복사하지만 ,arraycopy()는 지정된 범위의 값들을 한번에 통째로 복사한다.각 요소들이 연속적으로 저장되어 있다는 특성때문에 이렇게 처리하는 것이 가능하다.

System.arraycopy(num, 0, newNum, 0, num.length);
num[0]에서 newNum[0]으로 num.length개의 데이터를 복사
다른배열과 달리 char배열은 for문을 사용하지 않고도 print()나 println으로 배열에 저장된 모든 문자를 출력할 수 있다.

1.6 배열의 활용

1.최대값 최소값 - 배열의 요소중 max값과 min값 찾기

public class Test01 {
	public static void main(String[] args) {
		int[] score = {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];
			}
		}
		System.out.println("최대값 : " + max);
		System.out.println("최소값 : " + min);
	}
}

최대값 : 100
최소값 : 33

2.(섞기) - 배열의 요소의 순서를 반복해서 바꾼다(카드섞기,로또번호 생성)

public class Test02 {
	public static void main(String[] args) {
		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중의 한 값을 임의로 얻는다.
			
			//아래 3줄, numArr[0]과 numArr[n]의 값을 서로 바꾼다. 
			int tmp = numArr[0];
			numArr[0] = numArr[n];
			numArr[n] = tmp;
		}
		
		for(int i = 0; i < numArr.length; i++) {
			System.out.print(numArr[i]);
		}	
	}
}

두 컵에 담긴 내용물을 서로 바꾸려면, 하나의 빈 컵이 더 필요한 것처럼. 두 변수에 저장된 값을 서로 바꾸려면, 별도의 저장공간이 하나 더 필요하다.
중복된 값이 없는 배열에서 값들의 위치만 서로 바꾸는 것이므로 중복된 값이 나올 수 없다.

3.로또번호를 생성하는 예제.

길이가 45인 배열에 1번부터 45까지의 값을 담은 다음 반복문을 이용해서 배열의 인덱스가i인 값(ball[i]과 random()에 의해서 결정된 임의의 위치에 있는 값과 자리를 바꾸는 것을 6번 반복한다.
이것은 마치 1부터 45까지의 번호가 쓰인 카드를 잘 섞은 다음 맨 위의 6장을 꺼내는 것과 같다고 할 수 있다.

public class Test03 {
	public static void main(String[] args) {
		int[] ball = new int[45]; // 45개의 정수값을 저장하기 위한 배열 생성
		
		//배열의 각 요소에 1~45의 값을 저장.
		for(int i = 0; i < ball.length; i++) {
			ball[i] = i + 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[j] = temp;			
		}
		
		//배열 ball의 앞에서부터 6개의 요소를 출력한다.
		for(int i = 0; i < 6; i++) {
			System.out.printf("ball[%d]=%d%n", i, ball[i]);
		}
	}
}

2. String배열

배열의 타입이 String인 경우에도 int배여릐 선언과 생성방법은 다르지 않다.
String[] name = new String[3];

2.1 String배열의 선언과 생성

String[] name = new String[3];
name[0] = "Cho";
name[1] = "Park";
name[2] = "Yi";

2.2 String배열의 초기화

String[] name = {"Cho", "Park", "Yi"}
원래 String은 클래스이므로 new연산자를 통해 객체를 생성해야한다.
String[] name = new String[3];

배열에 실제 객체가 아닌 객체의 주소가 저장되어 있는 것을 볼 수 있다. 이처럼, 기본형 배열이 아닌 경우, 즉, 참조형 배열의 경우 배열에 저장되는 것은 객체의 주소이다.

2.3 char배열과 String클래스

문자열이라는 용어는 '문자를 연이어 늘어놓은 것'
문자배열인 char배열과 같은 뜻.
자바에서 char배열이 아닌 String클래스를 이용해서 문자열을 처리하는 이유는 String클래스가 char배열에 여러 가지 기능을 추가하여 확장한 것이기 때문이다. 그래서 char 배열을 사용하는 것보다 String클래스를 사용하는 것이 문자열을 다루기 더 편리하다.

String클래스는 char배열에 기능(메서드)을 추가한것이다.

기능은 함수를 의미하며, 메서드는 객체지향 언어에서 '함수'대신 사용하는 용어일 뿐 함수와 같은 뜻이다. 앞으로 '기능'이나 '함수'대신 '메서드'라는 용어를 사용할 것이다.

char배열과 String클래스의 한 가지 중요한 차이가 있는데 ,String객체(문자열)는 읽을 수만 있을 뿐 내 ㅍ용을 변경 할 수 없다.

String str = "java"
str = str + "8"
System.out.println(str);
위의 문장에서 문자열 str의 내용이 변경되는 것 같지만, 문자열은 변경할 수 없으므로 새로운 내용의 문자열이 생선된다.

String클래스의 주요 메서드

char charAt(int index) : 문자열에서 해당(index)위치 반환
charAt메서드는 문자열에서 지정된 Index에 있는 한 문자를 가져온다. 배열에서 '배열이름[index]'로 index에 위치한 값을 가져오는 것과 같다고 생각하면 된다. 배열과 마찬가지로 char메서드의 index 값은 0부터 시작한다.

int length() : 문자열의 길이 반환

String substring(int from, int to) 문자열에서 해당 범위(from~to)에 있는 문자열 반환, to는 범위 포함 안됨

boolean equals(object obj) 문자열의 내용이 obj와 같은지 확인한다. 같으면 결과는 true, 다르면 flase가 된다.

char[] toCharArray() : 문자열을 문자배열(char[])로 변환해서 반환한다.

char배열과 String클래스의 변환
가끔은 char배열을 String으로 변환하거나, 또는 그 반대로 변환해야하는 경우가 있다. ';ㅣ
char[] chArr = { 'A', 'B', 'C'};
String str = new String(chArr); // char배열 -> String
char[] tmp = str.toCharArray(); //String -> char배열

2.4 커맨드 라인을 통해 입력받기

Scanner클래스의 nextLine()외에도 화면을 통해 사용자로부터 값을 입력받을 수 있는 간단한 방법이 있다.

c:\jdk1.8\work\ch5\java MainTest abc 123

커맨드라인을 통해 입력된 두 문자열은 String배열에 담겨서 MainTest클래스의 main메서드의 매개변수(args)에 전달된다. 그리고는 main 메서드 내에서 args[0],args[1]과 같은 방식으로 커맨드라인으로 부터 전달받은 문자열에 접근할 수 있다.
여기서 args[0]은 "abc"이고 args[1]은 "123"이 된다.

커맨드라인에 입력된 매개변수는 공백문자로 구분하기 때문에 입력될 값에 공백이 있는 경우 큰 따옴표(")로 감싸주어야 한다.
숫자를 입력해도 숫자가 아닌 문자열로 처리된다는 것을 주의해야 한다. 문자열"123"을 숫자 123으로 바꾸려면
int num = Integer.parsInt("123"); //변수 num에 숫자 123이 저장된다.

커맨드 라인에 매개변수를 입력하지 않으면 크기가 0인 배열이 생성되어 args.length의 값은 0이 된다. 앞서 배운 것 처럼 이렇게 크기가 0인 배열을 생성하는 것도 가능하다. 만일 입력된 매개변수가 없다고 해서 배열을 생성하지 않으면 참조변수 args의 값은 null이 될 것이고, 배열 args를 사용하는 모든 코드에서 에러가발생할 것이다. 이러한 에러를 피하려면, 다음과 같이 main 메서드에 if문을 추가해줘야 한다.

public static void main (String[] args) {
	if(args != null) {
    	System.out.println("매개변수의 개수:"+args.length);
        for(int i = 0; i < args.length; i++; {
        	System.out.println("args[" + i + "] = \"" + args[i] + "\"");

그러나 JVM이 입력된 매개변수가 없을 때, null대신 크기가 0인 배열을 생성해서 args에 전달하도록 구현되어 우리는 이러한 수고를 덜었다.

3. 다차원 배열

2차원 이상의 배열, 즉 다차원 배열도 선언해서 사용할 수 있다.

3.1 2차원 배열의 선언과 인덱스

2차원 배열 선언 방법
타입[][] 변수이름; -> int[][] score;
2차원 배열은 주로 테이블 형태의 데이터를 담는데 사용되며, 만일 4행 3열의 데이터를 담기 위한 배열을 생성하려면 다음과 같이 해야한다.
int[][] score = new int[4][3]; // 4행 3열의 2차원 배열을 생성한다.

2차원 배열의 index
2차원 배열은 행(row)과 열(column)로 구성되어 있기 때문에 Index도 행과 열에 각각 하나씩 존재한다. '행index'의 범위는 '0~행의 길이-1'이고 '열index'의 범위는 '0~열의 길이-1'이다. 2차원 배열의 각 요소에 접근하는 방법은 '배열이름[행index][열index]'이다.

3.2 2차원 배열의 초기화

int[][] score = {
					{100, 100, 100}
                   ,{20, 20, 20,}
                   ,{30, 30, 30}
};

3.3 가변 배열

2차원 이상의 배열을 '배열의 배열'의 형태로 처리한다는 사실을 이용하면 보다 자유로운 형태의 배열을 구성할 수 있다.

3.4 다차원 배열의 활용

다차원 배열의 대표적인 에제

1.좌표에 X표하기 : 입력한 2차원 좌표의 위치에 x표시 하기
2.빙고 : 빙고판을 만들고 입력받은 숫자를 빙고판에서 지운다
3.행렬의 곱셈 : 두 행렬을 곱한 결과를 출력
4.단어 맞추기 : 영어 단어를 보여주고, 뜻을 맞추는 게임

예제 : 좌표에 x표하기

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		final int SIZE = 10;
		int x = 0, y = 0;	
	  	char[][] board = new char[SIZE][SIZE];
		byte[][] shipBoard = {
				//1  2  3  4  5  6  7  8  9
				{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1
				{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2
				{ 0, 1, 0, 0, 0, 0, 0, 0, 0 }, // 3
				{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 4
				{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 5
				{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 6
				{ 1, 1, 0, 0, 0, 0, 0, 0, 0 }, // 7
				{ 0, 0, 0, 1, 0, 0, 1, 0, 0 }, // 8
				{ 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 9
				
		};
		
		//1행에 행번호를, 1열에 열번호를 저장한다.
		for(int i = 1; i < SIZE; i++) {
			board[0][i] = board[i][0] = (char)(i+'0');
		}
		
		Scanner scanner = new Scanner(System.in);
		
		while(true) {
			System.out.print("좌표를 입력하세요.(종료는 00)");
			String input = scanner.nextLine(); //화면에 입력받은 내용을 input에 저장
			
			if(input.length() == 2) { 		//두글자를 입력한 경우 
				x = input.charAt(0) - '0'; 	//문자를 숫자로 변환 
				y = input.charAt(1) - '0';
				
				if(x == 0 && y == 0) // x와 y가 모두 0인 경우 
					break;
			}
			
			if(input.length() != 2 || x <= 0 || x >= SIZE || y <= 0 || y >= SIZE) {
				System.out.println("잘못된 입력입니다. 다시 입력해주세요");
				continue;
			}
			
			//shipBoard[x-1][y-1]의 값이 1이면, '0'을 board[x][y]에 저장한다.
			board[x][y] = shipBoard[x-1][y-1] == 1 ? 'O' : 'X';
			
			//배열 board의 내용을 화면에 출력한다.
			for(int i = 0; i < SIZE; i++) {
				System.out.println(board[i]); //board[i]는 1차원 배열
			}
			System.out.println();
			
		}
	}
}

board는 char배열이므로, 숫자를 문자로 변환해서 저장해야 한다.
그래서 변수 i에 문자 '0'을 더한다. 숫자 1에 문자'0'을 더하면 문자 '1'이 된다.

2차원 char배열의 각 요소는 1차원 배열이므로 아래의 왼쪽과 같이 간단히 출력할 수 있다. 원래는 오른쪽과 같이 배열의 각 요소를 하나씩 출력해야 하는데, println메서드로 1차원 char배열의 참조변수를 출력하면, 배열의 모든 요소를 한줄로 출력한다.

예제 : 영어단어 맞추기

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		String[][] words = {
				{"chair", "의자"},		//words[0][0], words[0][1]
				{"computer", "컴퓨터"}, //words[1][0], words[1][1]
				{"integer", "정수"}, 	//words[2][0], words[2][1]
				
		};
		Scanner scanner = new Scanner(System.in);
		
		for(int i = 0; i < words.length; i++) {
			System.out.printf("Q%d. %s의뜻은?", i+1, words[i][0]);
			
			String tmp = scanner.nextLine();
			
			if(tmp.equals(words[i][1])) {
				System.out.printf("정답입니다.%n%n");
			} else {
				System.out.printf("틀렸습니다. 정답은 %s입니다.&n&n", words[i][1]);
			}
		}
	}
}

words[i][0]은 문제이고, words[i][1]은 답이다. words[i][0]을 화면에 보여주고, 입력받은 답은 tmp에 저장한다.
그 다음엔 equal()로 tmp와 words[i][1]을 비교해서 정답인지 확인한다.

profile
하루하루 최선을

0개의 댓글