int a; //변수는 변수 1개당 값 1개 저장
a = 10;
System.out.print(a); //10
a = 20
System.out.print(a); //20
변수는 변수 1개 당 값 1개를 저장한다.
그러나 컴퓨터는 대용량의 정보를 처리해야 할 일이 많다. ---> 배열
배열
- 집합 데이터 처리를 수월하게 해줌
- 하나의 배열에 여러개의 값 저장 가능
- 타입이 동일한 값만 저장
- 배열의 크기는 고정 == 방을 늘릴 수 없음!!!!! (arraylist >> 타입, 크기 자유로움)
- count도 안됨.
==== 타입, 크기 고정
1) 배열 선언
타입이름 [] ;
int [] a;
char [] b;
- 선언만 한다고 방이 만들어지지 않음(객체타입이기 때문) ===> 생성 까지 해야함
( 변수 당 방 1개, 배열은 방을 여러개 만들 수 있음)
2) 배열 생성
변수이름 = new 타입[방 개수];
a = new int[5];
b = new char[3];
보통 선언과 생성을 같이 쓴다.
int[] a = new int[5];
char[] b = new char[3];
지역변수(함수 안에서 선언한 변수)는 값을 초기화하지 않으면 쓰레기값이 들어가있다.
>> int i = 0;
배열은 자동으로 초기화 해준다. --- heap에 저장되기 때문
heap에 저장되는 값은 자동 초기화 됨. -- 멤버변수, class, 배열,,
stack에 저장되는 값은 자동 초기화X => 쓰레기값 됨.
배열 변수 순서는 0부터 시작
<배열의 인덱스>
>> a[0], a[1], a[2] , ...
int[] a = new int[4];
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
a[4] = 5;
System.out.print(a[0]);
System.out.print(a[1]);
System.out.print(a[2]);
System.out.print(a[3]);
System.out.print(a[4]);
↓
int[] a = new int[5];
//배열명.length: 배열의 길이 값을 갖는 속성
for (int i = 0; i < a.length; i++) {
a[i] = i + 1;
}
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
//문자열 배열
String[] c = new String[2];
c[0] = "aaa";
c[1] = "bbb";
for (int i = 0; i < c.length; i++) {
System.out.println(c[i]);
}
* 형 변환
값들은 모두 타입을 갖는다. -- 3.14(float), 5(int)
타입이 다른 값을 연산할 때에는 형 변환을 해야 한다.
ex) 3.14 + 5
컴퓨터는 자동으로 타입을 변환시켜 연산함 -- 자동 형변환
ex) 3.14 + 5.0
//char 타입 배열, 방 3개.
char[] b = new char[3];
char ch = 'a';
for (int i = 0; i < b.length; i++) {
// char 이 int로 바뀌어 계산(자동 형변환) -> char로 강제 형변환시켜 타입에 넣음.
b[i] = (char) (ch + i);
}
for (int i = 0; i < b.length; i++) {
System.out.println(b[i]);
}
* 자동 형변환
- 타입이 서로 다른 값을 연산할 때 자동으로 작은 타입을 큰 타입으로 변환.
- 연산자 필요 없음
* 강제 형변환
- 강제로 타입 변환
- 캐스팅 연산자를 작성해야 함
- 캐스팅 연산자: (타입)
3) 배열 초기화
응용) 파라메터 값에 배열 초기화해서 넣기
예1. 도형 그리기
- 파라메터 값에 배열 넣어 호출.
Point[] arr = new Point[] {new Point (6,9)} ; // 초기화 해서 생성. 방 값 안넣음
(=)
new Point[] {new Point(6,9)}
package oop2;
//한 개의 좌표
class Point {
int x;
int y;
public Point() {
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "Point [x=" + x + ", y=" + y + "]";
}
}
//도형 그리기 클래스
abstract class Shape {
Point[] points; // 포함관계: 멤버변수로 다른 타입의 클래스
public abstract void draw(); // 하위 클래스에서 각 클래스에 적합하게 구현
}
class Circle extends Shape {
int r; // 반지름 변수
public Circle() {
points = new Point[1]; //배열 생성
points[0] = new Point(5, 5); // 중심점 좌표
r = 10; //반지름
}
// 파라메터로 받은 값으로 멤버변수 초기화
public Circle(Point[] arr, int r) {
points = arr;
this.r = r;
}
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println("원을 그림");
System.out.println("중심점: " + points[0]);
System.out.println("반지름: " + r);
}
}
public class ShapeMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
Shape c1 = new Circle();
c1.draw();
Shape c2 = new Circle(new Point[] {new Point(6, 9)}, 7);
c2.draw();
}
}
=================================================
(print)
원을 그림
중심점: Point [x=5, y=5]
반지름: 10
원을 그림
중심점: Point [x=6, y=9]
반지름: 7
================================================
int i;
int[] arr1 = { 1, 2, 3, 4, 5 }; // 방이 5개 만들어지고 1~5로 초기화
System.out.println("arr1 방 개수:" + arr1.length);
for (i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]);
}
int[] arr2 = new int[] {10, 20, 30}; // new로도 초기화 가능 (크기 지정하면 에러)
System.out.println("arr2 방 개수:" + arr2.length);
for (i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}
char[] arr3 = { 'a', 'b', 'c' };
System.out.println("arr3 방 개수:" + arr3.length);
for (i = 0; i < arr3.length; i++) {
System.out.println(arr3[i]);
}
String[] arr4 = { "aaa", "bbb" };
System.out.println("arr4 방 개수:" + arr4.length);
for (i = 0; i < arr4.length; i++) {
System.out.println(arr4[i]);
}
* 입력하는 값이 배열 안에 들어가도록 하기
Scanner sc = new Scanner(System.in);
int i;
int[] arr = new int[5];
for (i=0; i < arr.length; i++) {
System.out.println("숫자를 입력하시오");
arr[i] = sc. nextInt();
}
for (i=0; i < arr.length; i++) {
System.out.println(arr[i]);
}
4) 배열 복사
static, heap, stack에 저장된 메모리가 각각 할당되어 사용됨
JAVA 는 사용하지 않는 메모리를 자동으로 해제해줌.
static | 정적 메모리 | ||
heap | 배열, 객체 (new ...) |
주소로만 접근 가능 (객체 이름(4B)에 주소값에 해당하는 참조값 매칭) |
자동 초기화 O |
stack | 메서드 (: 클래스 안에 있는 함수) (main() ...) |
변수 이름으로 접근 가능 (변수 이름 == 주소) |
자동 초기화 X (이전에 실행된 내용이 지워지지 않고 쓰레기 값으로 남아있음 |
int[] c = new int[3];
>> new가 heap에 메모리를 3만큼 할당받아서
그 주소값을
c(참조변수)(stack)에 참조값으로 대입
>> 참조값은 주소값 대용으로 사용됨
(1) 얕은 복사
- 참조값만 복사하는 것. (참조값은 주소 역할)
- 요소(배열 방에 있는 값)를 변경하면 다른 쪽에 영향을 줌
int[] a = {1,2,3,4,5}; //방 5개 만들어짐
int[] b = a; // 몸은 하나인데 이름이 두개
b[1] = 20; // --> a = {1, 20, 3, 4, 5}
int[] a = { 1, 2, 3, 4, 5 };
int[] b = a;
int i;
System.out.println("배열 a 요소");
for (i = 0; i < a.length; i++) {
System.out.print(a[i] + "\t");
}
System.out.println();
System.out.println("배열 b 요소");
for (i = 0; i < b.length; i++) {
System.out.print(b[i] + "\t");
}
System.out.println();
System.out.println("배열 a 참조값:" + a);
System.out.println("배열 b 참조값:" + b);
b[1] = 20; // b의 1번방 변경
System.out.println("b[1] 변경 후 배열 a 요소");
for (i = 0; i < a.length; i++) {
System.out.print(a[i] + "\t");
}
System.out.println();
System.out.println("b[1] 변경 후 배열 b 요소");
for (i = 0; i < b.length; i++) {
System.out.print(b[i] + "\t");
}
System.out.println();
============================================
(print)
배열 a 요소
1 2 3 4 5
배열 b 요소
1 2 3 4 5
배열 a 참조값:[I@251a69d7
배열 b 참조값:[I@251a69d7
b[1] 변경 후 배열 a 요소
1 20 3 4 5
b[1] 변경 후 배열 b 요소
1 20 3 4 5
(2) 깊은 복사
- 배열의 요소는 동일하지만 다른 메모리에 복사하는 것. ==> 참조값, 변경 후 요소 다름
- 직접 구현할 수도 있고 api 메서드를 사용할 수도 있다.
* 직접 구현
int[] a = {1,2,3,4,5}; //원본배열 생성
int[] b = new int[a.length]; //복사배열을 원본 배열과 동일한 크기로 생성
int i;
for (i = 0; i < a.length; i++) {
b[i] = a[i]; //원본 배열 요소를 b에 복사
}
System.out.println("원본 배열");
for (i = 0; i < a.length; i++) {
System.out.print(a[i] + "\t");
}
System.out.println();
System.out.println("복사 배열");
for (i = 0; i < b.length; i++) {
System.out.print(b[i] + "\t");
}
System.out.println();
System.out.println("배열 a 참조값:" + a);
System.out.println("배열 b 참조값:" + b);
b[1] = 20; // b의 1번방 변경
System.out.println("b[1] 변경 후 배열 a 요소");
for (i = 0; i < a.length; i++) {
System.out.print(a[i] + "\t");
}
System.out.println();
System.out.println("b[1] 변경 후 배열 b 요소");
for (i = 0; i < b.length; i++) {
System.out.print(b[i] + "\t");
}
System.out.println();
================================================
(print)
원본 배열
1 2 3 4 5
복사 배열
1 2 3 4 5
배열 a 참조값:[I@251a69d7
배열 b 참조값:[I@7344699f
b[1] 변경 후 배열 a 요소
1 2 3 4 5
b[1] 변경 후 배열 b 요소
1 20 3 4 5
* api 메서드 사용
System.arraycopy(원본 배열, 원본 복사시작위치, 대상 배열, 대상 복사시작위치, 복사 요소 개수);
int[] a = {1,2,3,4,5}; //원본 배열
int[] b = new int[a.length]; //복사 배열
int i;
//요소 복사 메서드
System.arraycopy(a, 0, b, 0, 3);
System.out.println("원본 배열");
for (i = 0; i < a.length; i++) {
System.out.print(a[i] + "\t");
}
System.out.println();
System.out.println("복사 배열");
for (i = 0; i < b.length; i++) {
System.out.print(b[i] + "\t");
}
System.out.println();
======================================
(print)
원본 배열
1 2 3 4 5
복사 배열
1 2 3 0 0
5) 2차원 배열
- 배열의 배열 --- 요소로 배열을 갖는 배열
- 객체를 사용하면 크게 사용할 일 없지만, 알고리즘 테스트 볼 때 알고 있으면 유용.
int[][] a = new int[3][2];
>> a는 방이 3개. 각 방이 int[2]을 요소로 갖는다.
// 3차원은 [][][]
a = 3 | a[0] // j = 0 | a[1] // j = 1 | a[0][0] = 1; a[0][1] = 2; a[1][0] = 3; a[1][1] = 4; a[2][0] = 5; a[2][1] = 6; |
a[0] = 2 | 1 | 2 | |
a[1] = 2 | 3 | 4 | |
a[2] = 2 | 5 | 6 |
int[][] a = new int[2][3];
System.out.println("a의 크기" + a.length);
System.out.println("a[0]의 크기: " + a[0].length);
System.out.println("a[1]의 크기: " + a[1].length);
int i, j, cnt = 1;
for (i = 0; i < a.length; i++) { //줄 수
for(j = 0; j < a[i].length; j++) { //각 줄의 칸 수
a[i][j] = cnt ++;
}
}
System.out.println("a의 요소");
for (i = 0; i < a.length; i++) { //줄 수
for(j = 0; j < a[i].length; j++) { //각 줄의 칸 수
System.out.println("a[" + i + "][" + j + "] = " + a[i][j]);
}
}
==================================
(print)
a의 크기2
a[0]의 크기: 3
a[1]의 크기: 3
a의 요소
a[0][0] = 1
a[0][1] = 2
a[0][2] = 3
a[1][0] = 4
a[1][1] = 5
a[1][2] = 6
* 2차원 배열 초기화
int[][] b = {{5, 6}, {8, 9}};
>> 2줄 2칸 배열 생성
b[i][j] | b[0] // j = 0 | b[1] // j = 0 |
b[0] // i = 0 | 5 | 6 |
b[1] // i = 1 | 8 | 9 |
int[][] b = {{5, 6}, {8, 9}}; //2줄 2칸 배열 생
for (i = 0; i < b.length; i++) {
for (j = 0; j < b[i].length; j++) {
System.out.println(b[i][j]);
}
}
================================
(print)
5
6
8
9
* 2차원 배열 가변 초기화
- 각 줄마다 칸 수 다르게 가능함.
int [][] c = {{1, 2, 3, 4}, {5, 6}};
// c의 크기: 2 ---- {1, 2, 3, 4}, {5, 6}
// c[0]의 크기: 4 ---- 1, 2, 3, 4
// c[1]의 크기: 2 ---- 5, 6
int[][] c = {{1, 2, 3, 4}, {5, 6}};
System.out.println("c의 크기: " + c.length);
for (i=0; i < c.length; i++) {
System.out.println("c[" + i + "]의 크기: " + c[i].length);
for (j = 0; j < c[i].length; j++) {
System.out.println(c[i][j]);
}
}
==============================
(print)
c의 크기: 2
c[0]의 크기: 4
1
2
3
4
c[1]의 크기: 2
5
6