Java/Doit!자바프로그래밍입문_개념정리

Java 입문 기초 정리_ 배열과 ArrayList

김쟈워니 2024. 5. 2. 10:32
배열이란?

 

  •  자료를 순차적으로 관리하는 구조,배열
    • 정수 20개를 이용한 프로그램을 할 때 20개의 정수 타입의 변수를 선언해야한다고 예시를 들면
    • int num1,num2,num3,...,num20;
    • 비효율적이고 변수 관리도 어려움
      • 배열은 동일한 자료형의 변수를 한꺼번에 순차적으로 관리가 가능
      • 자료가 연속으로 나열된 자료 구조. 
    • 배열의 길이는 length
    • 데이터가 들어가는 정도가 size 
      • 배열에 대한 용어가 아님,ArrayList 등의 컬렉션 클래스 데이터 크기 나타내는 것
  • 배열의 선언
    • 배열의 크기가 몇 인지 선언해야 함.(fixed-length)
    • 중간에 자료 빌 수 없음, 연속되는 자료
    • 선언을 이미 했는데 공간이 부족하다면 새로운 배열을 만들어서 내용을 복사해야함.
      • 자동으로 줄거나 늘지 않음
1) 자료형[] 배열이름 = new 자료형[개수];
ex) int[] arr = new int[10];
2) 자료형 배열이름[] = new 자료형[개수];
ex) int arr[] = new int[10];

 

  • 배열의 메모리 구조 

int[] arr = new int[10] 의 메모리 구조

  • 배열의 초기화
    • 배열도 선언과 초기화를 동시에 할 수 있음
    • 배열을 초기화 할 때는 개수를 명시하지 않음
  • 배열의 선언과 초기화를 동시에 하는 경우 예시
// 배열의 초기화
		int[] studentID1 = new int[] { 101, 102, 103 }; // 개수 생략
		// int[] studentID2= new int[3] {101,102,103};//초기화 할떄 [] 안에 개수를 쓰면 오류가 발생함
		// Cannot define dimension expressions when an array initializer is provided
		// 오류 발생

		int[] studentID3 = { 101, 102, 103 }; // new int[]부분을 생략
		System.out.println(studentID1.length);// 결과:3
		System.out.println(studentID3.length);// 결과:3
  • 배열의 선언과 초기화를 동시에 하는 경우 new 자료형[] 부분을 생략할 수 있다.
  • 배열을 초기화 하고 바로 값을 넣는 경우 자료형 [] 안에 배열 개수를 쓰면  Cannot define dimension expressions when an array initializer is provided 오류가 발생함

 

  • 배열을 선언 후 초기화를 하는 경우 예시
// 배열 선언후 초기화
		int[] studentID4;
		studentID4 = new int[] { 101, 102, 103 };
		// 선언 후 초기화 할떄는 new int[]를 생략할 수 없음
  • 선언 후 초기화 할 때는 new 자료형[] 이 부분을 생략할 수 없다.
  • 배열 선언 후 인덱스를 사용하여 배열에 값 넣기 예시
// 이미 생성된 배열에 값 넣기
		int[] numbers3 = new int[3];
		numbers3[0] = 1;
		numbers3[1] = 2;
		numbers3[2] = 3;
  • 배열의 순서는 0 부터 시작
    • 5개 길의의 배열을 만들었다면 0,1,2,3,4
    • n개 길이의 배열을 만들었다면 0,1,2,3...,n-1
  • 배열을 출력하는 법
// 배열을 출력하는 법
		// System.out.println(배열이름); 으로 출력할 경우에는 주소값이 나옴
		// 반복문을 활용하여 배열안에 요소들을 출력함
		for (int i = 0; i < numbers3.length; i++) {
			System.out.println(numbers3[i]);
  • 배열은 반복문을 통하여 출력해야 한다.

 

  • 선언만 하고 초기 화 하지 않을 경우 
//정수형 배열에 선언 후 값을 안넣으면 default 값은 0
		int[] integer = new int[3];
		for (int i = 0; i < integer.length; i++) {
			System.out.print(integer[i]+"/");
		} //결과: 0/0/0/
		System.out.println();
		
		//실수형 배열에 선언 후 값을 안넣으면 default 값은 0.0
		double[] double1 = new double[3];
		for (int i = 0; i < double1.length; i++) {
			System.out.print(double1[i]+"/");
		} //결과:0.0/0.0/0.0/
		
		System.out.println();
		
		//객체 배열은 선언 후 값을 안넣으면 default 값은null 
		String [] stringTest= new String[3];
		for (int i=0; i<stringTest.length;i++) {
			System.out.print(stringTest[i]+"/");
		}//결과: null/null/null/

 

  • 배열의 자료형에 따라 정수는 0/ 실수는 0.0 객체 배열은 null 로 초기화됨

 

  • 배열 사용하기
    • []: 인덱스 혹은 첨자 연산자
    •  배열의 위치를 지정하여 자료를 가져옴
    • 모든 배열의 순서는 0부터 시작함
    • n개 배열은 0부터 n-1 위치까지 자료가 존재
  • 배열의 길이와 유효한 요소 값
    • 배열의 길이의 속성:length
    • 자료가 있는 요소만 출력하려면 크기에 대한 저장을 따로 해야함
double[] num1 = new double[5];
		num1[0] = 10.0;
		num1[1] = 20.0;
		num1[2] = 30.0;

		double total = 0.0;
		for (int i = 0; i < num1.length; i++) {
			total += num1[i];
		}

		System.out.println(total); // 결과:60.0

		double total2 = 1.0;
		for (int i = 0; i < num1.length; i++) {
			total2 *= num1[i];
		}
		System.out.println(total2);// 결과:0.0;
		// index가 3, 4 인 친구들이 0 으로 초기화 되어있기 때문에
	// 유효한 숫자만큼만 계산하고 싶을때;
		double[] num2 = new double[5];
		int size = 0; // 유효한 값이 저장된 배열 요소 개수를 저장할 변수 선언

		// 값을 저장한 후 size 변수 값 증가 시킴
		num2[0] = 10.0;
		size++;
		num2[1] = 20.0;
		size++;
		num2[2] = 30.0;
		size++;

		double total3 = 1.0;
		for (int i = 0; i < size; i++) {//유효한 값이 저장된 배열 요소 개수만큼 반복문 실행
			total3 *= num2[i];
		}
		System.out.println(total3);//1.0*10.0*20.0*30.0 인 6000.0이 나오는 모습 확인 가능
  • 배열에 알파벳 넣기
package array;

public class ArrayTest3 {

	public static void main(String[] args) {
		char[] alphabets=new char[26];
		char ch='A';//65

		for(int i=0;i<alphabets.length;i++){
			alphabets[i]= ch;
			ch++;
		}
		for(int i=0;i<alphabets.length;i++) {
			System.out.println(alphabets[i]);
		}
	}


}

 

객체 배열 사용하기
  • 참조 자료형을 선언하는 객체 배열
  • 배열만 생성한 경우 요소는 null로 초기화 됨
  • 각 요소를 new를 활용하여 생성하여 저장해야함
  • 예시 책 객체 배열 만들기
package array;

public class Book {

		private String bookName;
		private String author;
		
		public Book() {}//기본생성자
		public Book(String bookName,String author) {//책의 이름과 저자를 매개변수로 갖는 생성자
			this.bookName=bookName;
			this.author=author;
		}
		
		//private으로 설정했기 때문에 외부에서 접근하기 위한 getter,setter 메서드 작성
		public String getBookName() {
			return bookName;
		}
		public void setBookName(String bookName) {
			this.bookName = bookName;
		}
		public String getAuthor() {
			return author;
		}
		public void setAuthor(String author) {
			this.author = author;
		}
		
		public void showBookInfo() {//책의 정보를 보여주는 메서드
			System.out.println(bookName+","+author);
			
		}
		
		
}

 

package array;

public class BookArray {

	public static void main(String[] args) {
		Book[] library = new Book[5];

		for (int i = 0; i < library.length; i++) {
			System.out.println(library[i]);
		}//결과는 null 5개


		// 책 5권이 만들어지는 것이 아닌, 책의 주소 5개가 만들어지는 것.

		library[0] = new Book("태박산맥", "조정래");
		library[1] = new Book("데미안", "헤르만 헤세");
		library[2] = new Book("어떻게 살 것인가", "유시민");
		library[3] = new Book("토지", "박경리");
		library[4] = new Book("어린왕자", "생택쥐페리");

		for (int i = 0; i < library.length; i++) {
			library[i].showBookInfo(); //book 인스턴스 멤버들
		}
		for(int i=0;i<library.length;i++) {
			System.out.println(library[i]); // book 인스턴스를 저장한 메모리 공간 주소
		}
	}

}

배열 복사하기
  • 기존 배열과 같은 배열을 만들거나 배열이 꽉 찬 경우 더 큰 배열을 만들고 기존 배열 자료를 복사 할 수 있음
  • System.arraycopy(src,srcPos,dest,destPos,length);
매개변수 설명
src 복사할 배열이름
srcPos 복사할 배열의 첫 번쨰 위치
dest 복사해서 붙여 넣을 대상 배열 이름
destPos 복사해서 대상 배열에 붙여 넣기를 시작할 첫번째 위치
length src에서 dest로 자료를 복사할 요소 개수
  • 배열 복사 예시
package array;

public class ArrayCopy {

	public static void main(String[] args) {
		int[] array1= {10,20,30,40,50};
		int[] array2= {1,2,3,4,5};
		
		System.arraycopy(array1, 0, array2, 1, 4);
		
		for(int i =0; i<array2.length;i++) {
			System.out.print(array2[i]+"/");//결과:1/10/20/30/40
		}
	}

}
  • 객체 배열 복사 예시
package array;

public class ObjectCopy1 {

	public static void main(String[] args) {
		Book[] bookArray1 = new Book[3];
		Book[] bookArray2 = new Book[3];
		
		bookArray1[0]= new Book("태백산맥","조정래");
		bookArray1[1]= new Book("데미안","헤르만 헤세");
		bookArray1[2]= new Book("어떻게 살 것인가","유시민");
		
		System.arraycopy(bookArray1, 0, bookArray2, 0, 3);
		//bookArray1의 [0](첫번째 index0)부터 bookArray2에 [0](첫번째 index)에 3(지정한 갯수)만큼
      		//복사함.
		for(int i =0; i<bookArray2.length;i++) {
			bookArray2[i].showBookInfo();
		}
	}

}
  • 얕은 복사: 배열 요소의 주소만 복사 되므로 배열 요소가 변경되면 복사된 배열의 값도 변경 됨.
package array;

public class ObjectCopy2 {

	public static void main(String[] args) {
		Book[] bookArray1 = new Book[3];
		Book[] bookArray2 = new Book[3];

		bookArray1[0] = new Book("태백산맥", "조정래");
		bookArray1[1] = new Book("데미안", "헤르만 헤세");
		bookArray1[2] = new Book("어떻게 살 것인가", "유시민");

		System.arraycopy(bookArray1, 0, bookArray2, 0, 3);
		for (int i = 0; i < bookArray2.length; i++) {
			bookArray2[i].showBookInfo();
		} // 결과: 위에 3권

		bookArray1[0].setBookName("나목");
		bookArray1[0].setAuthor("박완서");

		System.out.println("=======bookArray1=======");
		for (int i = 0; i < bookArray1.length; i++) {
			bookArray1[i].showBookInfo();
		}

		System.out.println("=======bookArray2=======");
		for (int i = 0; i < bookArray2.length; i++) {
			bookArray2[i].showBookInfo();
		}
		// 값을 변경한 것은 bookArray1 이지만 bookArray2의 값도 변경됨//변경사항이 반영됨

		/* 결과:
		 * 태백산맥,조정래
		 * 데미안,헤르만 헤세
		 * 어떻게 살 것인가,유시민
		 * =======bookArray1=======
		 * 나목,박완서
		 * 데미안,헤르만 헤세
		 * 어떻게 살 것인가,유시민 
		 * =======bookArray2======= 
		 * 나목,박완서 
		 * 데미안,헤르만 헤세 
		 * 어떻게 살 것인가,유시민
		 */
	}

}
  • 객체 배열의 요소에 저장된 값은 인스턴스 자체가 아니고 인스턴스의 주소 값이기 떄문
  • 객체 배열을 복사 할 때 인스턴스를 따로 생성하는 게 아니라 기존 인스턴스의 주소값만 복사
  • 결국 두 배열의 서로 다른 요소가 같은 인스턴스를 가리키고 있으므로 복사되는 배열의 인스턴스 값이 변경되면 두 배열 모두 영향을 받음.

 

  • 깊은 복사
    • System.arraycopy()메서드를 사용하든 반복문을 사용하든 객체 배열을 복사하면 항상 인스턴스 주소가 복사
    • 직접 인스턴스를 만들고 그 값을 복사 해야함
package array;

public class ObjectCopy3 {

	public static void main(String[] args) {
		Book[] bookArray1 = new Book[3];
		Book[] bookArray2 = new Book[3];

		bookArray1[0] = new Book("태백산맥", "조정래");
		bookArray1[1] = new Book("데미안", "헤르만 헤세");
		bookArray1[2] = new Book("어떻게 살 것인가", "유시민");

		// 디폴드 생성자로 bookArray2 배열 인스턴스 생성
		bookArray2[0] = new Book();
		bookArray2[1] = new Book();
		bookArray2[2] = new Book();

		// bookArray1 배열 요소를 새로 생성한 bookArray2 배열 인스턴스에 복사
		for (int i = 0; i < bookArray1.length; i++) {
			bookArray2[i].setBookName(bookArray1[i].getBookName());
			bookArray2[i].setAuthor(bookArray1[i].getAuthor());
		}

		for (int i = 0; i < bookArray2.length; i++) {
			bookArray2[i].showBookInfo();
		}
		// 복사 후 배열2 요소 값 출력

		bookArray1[0].setBookName("나목");
		bookArray1[0].setAuthor("박완서");

		System.out.println("=======bookArray1=======");
		for (int i = 0; i < bookArray1.length; i++) {
			bookArray1[i].showBookInfo();
		}

		System.out.println("=======bookArray2=======");
		for (int i = 0; i < bookArray2.length; i++) {
			bookArray2[i].showBookInfo();

		}
		/*
		태백산맥,조정래
		데미안,헤르만 헤세
		어떻게 살 것인가,유시민
		=======bookArray1=======
		나목,박완서
		데미안,헤르만 헤세
		어떻게 살 것인가,유시민
		=======bookArray2=======
		태백산맥,조정래
		데미안,헤르만 헤세
		 */
	}
}
 public static void main(String[] args) {
        Book[] bookArray1 = new Book[3];
        Book[] bookArray2 = new Book[3];

        bookArray1[0] = new Book("태백산맥", "조정래");
        bookArray1[1] = new Book("데미안", "헤르만 헤세");
        bookArray1[2] = new Book("어떻게 살 것인가", "유시민");

        // 깊은 복사를 수행하여 bookArray2에 복사
        for (int i = 0; i < bookArray1.length; i++) {
            bookArray2[i] = new Book(bookArray1[i].getBookName(), bookArray1[i].getAuthor());
        }

        // bookArray2 출력
        for (int i = 0; i < bookArray2.length; i++) {
            bookArray2[i].showBookInfo();
        }
        
        // bookArray1의 첫 번째 요소를 변경
        bookArray1[0].setBookName("나목");
        bookArray1[0].setAuthor("박완서");

        // bookArray1 출력
        System.out.println("=======bookArray1=======");
        for (int i = 0; i < bookArray1.length; i++) {
            bookArray1[i].showBookInfo();
        }

        // bookArray2 출력
        System.out.println("=======bookArray2=======");
        for (int i = 0; i < bookArray2.length; i++) {
            bookArray2[i].showBookInfo();
        }
    }
}

두 가지다 깊은 복사, 차이는 반복문으로 bookArray2배열 인스턴스 생성하면서 바로 넣느냐 아니면 생성 후 넣느냐 차이

 

향상된 for 문
  • java 5부터 제공됨
  • 처음에서 끝까지 모든 요소를 참조할 때 사용하면 편리한 반복문
  • 향상된 for 문은 배열 요소값을 순서대로 하나씩 가져와서 변수에 대입
  • 따로 초기화와 종료 조건이 없기 떄문에 모든 배열의 시작 요소부터 끝요소까지 실행
for(변수:배열){
반복 실행문;
}
package array;

public class EnhancedForLoop {

	public static void main(String[] args) {
		String[] strArray= {"Java","Android","C","JavaScript","Python"};
		for(String lang:strArray) {
			System.out.println(lang);
		}
	}

}

 

  • 다차원 배열
    • 2차원 이상의 배열
    • -지도, 게임, 등 평면이나 공간을 구현 할 때 많이 사용 됨
  • 이차원 배열의 선언과 구조
자료형[][] 배열 이름 = new 자료형[행개수][열개수];
ex) int[][] arr = new int[2][3]

 

위에 선언한 배열의 구조는아래와 같음

arr[0][0] arr[0][1] arr[0][2]
arr[1][0] arr[1][1] arr[1][2]

 

선언과 초기화

int[][] arr ={{1,2,3},{4,5,6}};
1 2 3
4 5 6

 

이차원 배열 사용하기

전체 모든 요소를 출력하려면 중첨된 for 문을 사용해야 함.

package array;

public class TwoDimension {

	public static void main(String[] args) {
		int[][] arr = {{1,2,3},{4,5,6}};
		
		for(int i = 0;i<arr.length;i++) {
			for(int j=0;j<arr[i].length;j++) {
				System.out.println(arr[i][j]);
			}
			System.out.println();
		}

	}

}

arr[i]length: 열의 길이

arr.length: 행의 길이

package array;

public class TwoDimension2 {

	public static void main(String[] args) {
		int[][] arr= new int[2][3];
		
		for(int i=0; i<arr.length;i++) {
			for(int j=0;j<arr[0].length;j++) {
				System.out.println(arr[i][j]);
			}
			System.out.println();
		}
	System.out.println(arr.length);	
	System.out.println(arr[0].length);	
	}

}

ArrayList 클래스
  • 기존 배열은 길이를 정하여 선언하므로 사용 중 부족한 경우 다른 배열로 복사하는 코드를 직접 구현해야 함.
  • 중간의 요소가 삭제되거나 삽입 되는 경우도 나머지 요소에 대한 조정하는 코드를 구현해야 함.
  • ArrayList클래스는 자바에서 제공되는 객체 배열이 구현된 클래스
  • 여러메서드와 속성 등 사용하여 객체 배열을 편리하게 관리할 수 있음
  • 가장 많이 사용하는 객체 배열 클래스
메서드 설명
boolean add(E e) 요소 하나를 배열에 추가
E는 요소의 자료형을 의미
int size() 배열에 추가된 요소 전체 개수를 반환
E get(int index) 배열의 index위치에 있는 요소 값을 반환
E remove(int index) 배열의 index위치에 있는 요소 값을 제거하고, 그 값을 반환
boolean isEmpty() 배열이 비어있는지 확인

요소를 추가하거나 제거 할 때 각 내부에서 코드가 모두 구현되어 있으므로 배열을 직접 선언하여 사용하는 것보다 편리

 

ArrayList에 가져다놓고 F1 키누르면 설명서나옴

  •  Module java.base 밑에 Package java.util 밑에 Class ArrayList<E> 가 있음
  • java.lang.Object 밑에 java.util.AbstractCollection<E> 밑에 java.util.AbsractList<E> 밑에 java.util.ArrayList<E> 가 상속받아 생성되어 있음
  • E는 이 리스트안에 있는 요소들의 타입을 적으면 됨.

 

아래로 내려가면 method 들이 있음

 

  • 이름,매개변수,return 타입, 어떤 기능인지 확인하여 사용

 

ArrayList의 기본형식

ArrayList<E> 배열 이름 = new ArrayList<E>();

<E> 는 제너릭타입

E 에 어떤 객체 타입을 쓸건지 넣는 것

package arraylist;

import java.util.ArrayList;

public class ArrayListTest {
	public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<String>(); //
		list.add("aaa");
		list.add("bbb");
		list.add("ccc");
		
		for(String s: list) {
			System.out.println(s);
		}
		
		for(int i=0;i<list.size();i++) {
			System.out.println(list.get(i));
            		//list[i] 는 안됨 arrayList에서는 인덱스 연산자 기능을 제공하지 않음
		}
		
	}
}

어떤 타입으로 쓸지 명시하지 않고 쓰는 경우도 있음

package arraylist;

import java.util.ArrayList;

public class ArrayListTest2 {

	public static void main(String[] args) {
		ArrayList list = new ArrayList();
		list.add("aaa");
		list.add("bbb");
		list.add("ccc");

		for (Object obj : list) {

			String s = (String) obj;
			System.out.println(s);
		}

		// ArrayList에 요소를 추가할 때 제네릭을 사용하지 않으면
        	//기본적으로 Object 형태로 저장, 따라서 향상된 for문에서 요소를
		// 순회할 때 Object 형태로 가져오게 됨
        	//그 후에 각 요소를 String으로 캐스팅하여 사용하는 것이 올바른 접근

		for (int i = 0; i < list.size(); i++) {
			String s = (String) list.get(i); 
		}
       		 // 명시하지 않으면 object로 꺼내오기떄문에 명시적 형변환을 해야함
	}
}

 

그렇지만 명시하고 쓰는 걸 추천.

 

ArrayList클래스 사용하여 응용프로그램 만들기

학생 성적 출력 프로그램

1. 과목 클래스 구현

package arraylist;

public class Subject {
	private String name;
	private int scorePoint;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getScorePoint() {
		return scorePoint;
	}

	public void setScorePoint(int scorePoint) {
		this.scorePoint = scorePoint;
	}

}

2. 학생 클래스 구현

package arraylist;

import java.util.ArrayList; //eclipse는 ctrl+shift+o 를 누르면 자동임포트해줌.

public class Student {
	private int studentID;
	private String studentName;
	private ArrayList<Subject> subjectList;
	// 다양한 과목을 수강 할 수 있기 때문에 과목은 배열로 관리

	public Student(int studentID, String studentName) {
		this.studentID = studentID;
		this.studentName = studentName;
		
		subjectList = new ArrayList<Subject>();
	}
	
	public void addSubject(String name,int score) {
		Subject subject = new Subject();
		subject.setName(name);
		subject.setScorePoint(score);
		
		subjectList.add(subject);
	}
	
	public void showStudentInfo() {
	
		int total=0;
		for (Subject subject: subjectList) {
			total+=subject.getScorePoint();
			
			System.out.println(studentName +"님의" +subject.getName()+
					"과목의 성적은 "+subject.getScorePoint()+"점 입니다.");
			
		}
		System.out.println("총점은 "+ total);
	}
}

3. 실행

package arraylist;

public class StudentTest {

	public static void main(String[] args) {
		Student studentLee = new Student(1001,"Lee");
		studentLee.addSubject("국어", 100);
		studentLee.addSubject("수학", 90);

		studentLee.showStudentInfo();
		
		Student studentKim = new Student(1002,"Kim");
		studentKim.addSubject("국어", 70);
		studentKim.addSubject("수학", 70);
		
		studentKim.showStudentInfo();
	}

}