07 배열과 ArrayList
07.1.배열이란?
- 자료를 순차적으로 관리하는 구조, 배열
- 배열
- 자료가 연속으로 나열된 자료 구조
- 배열
- 배열 선언과 초기화
- 자료형[] 배열이름 = new 자료형[개수];
- 자료형 배열이름[] = new 자료형[개수];
- 배열 초기화하기
int[] studentIDs = new int[] {1,2,3}; //개수 생략가능 int[] studentIDs = new int[3] {1,2,3}; //오류!! int[] studentIDs = {1,2,3}; //int형 요소가 3개인 배열 생성 //배열 자료형 먼저 선언 후 초기화하는 경우 new int[] 생략 불가능 int[] studentIDs; //배열 자료형 선언 studentIDs = new int[] {1,2,3};
- 배열 사용하기
studentIDs[0] = 10; //배열의 첫 번째 요소에 값 10을 저장
- 인덱스 연산자[]
- 배열 이름에 []을 사용하는 것
- 물리적 위치와 논리적 위치
- 물리적 위치
- 배열이 메모리에서 실제 저장되는 곳
- 요소 10개 선언시 사용하는 실제 값도 바로 이웃한 메모리에 놓음
- ‘5 다음에 10이 있다’ 논리형 순서과 실제 메모리 비교시 값 5 가 놓인 메모리 주소에서 4바이트(int) 다음 메모리 주소값이 10이 놓임!
- 논리적 위치
- 이론상 배열 위치
- 배열이 외의 자료구조는 물리적 위치와 논리적 위치가 다른 경우가 존재!
- 물리적 위치
- 배열 순서는 0부터
public class ArrayTest { public static void main(String[] args) { int[] num = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; for (int i = 0; i < num.length; i++) { int i1 = num[i]; System.out.println("i1 = " + i1); } } }
- 배열의 첫 번째 요소 인덱스는 0부터 시작
- 배열의 모든 요소 합 출력
public class ArrayTest { public static void main(String[] args) { int[] num = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; int sum = 0; for (int i = 0; i < num.length; i++) { int i1 = num[i]; System.out.println("i1 = " + i1); sum += i1; } System.out.println("sum = " + sum); } }
- 전체 배열 길이와 유효한 요소 값
- 배열안에 대입되지 않은 값은 해당 자료형의 기본값으로 초기화됨
- 문자 저장 배열 만들기
public class CharArray { public static void main(String[] args) { char[] alpabets = new char[26]; char ch = 'A'; for (int i = 0; i < alpabets.length; i++, ch++) { alpabets[i] = ch; System.out.println("alpabet[i] = " + alpabets[i]+","+(int)alpabets[i]); } } }
- 알파벳 26개 저장.. 문자형 배열 선언
- 알파벳의 아스키 코드 값 출력..
- 객체 배열 사용
public class BookArray { public static void main(String[] args) { Book[] library = new Book[5]; //Book클래스 형으로 객체 배열의 생성 for (int i = 0; i < library.length; i++) { Book book = library[i]; System.out.println("book = " + book); } } //객체 배열은 기본 null로 초기화됩니다! }
- 배열 각 요소에 Book인스턴스를 만들어 저장!
public class BookArray2 { public static void main(String[] args) { Book[] library = new Book[5]; //Book클래스 형으로 객체 배열의 생성 library[0] = new Book("1", "1"); library[1] = new Book("11", "11"); library[2] = new Book("111", "111"); library[3] = new Book("1111", "1111"); library[4] = new Book("11111", "11111"); for (int i = 0; i < library.length; i++) { Book book = library[i]; System.out.println("book = " + book); } } //객체 배열은 기본 null로 초기화됩니다! } --- 출력 book = kr.or.test.Book@179d3b25 book = kr.or.test.Book@254989ff book = kr.or.test.Book@5d099f62 book = kr.or.test.Book@37f8bb67 book = kr.or.test.Book@49c2faae
- 각 출력 내용은 각 배열 요소가 가진 인스턴스 주소 값입니다.
- 배열 복사하기
- System.arraycopy(src,srcPos,dest,destPos,length)
- src : 복사할 배열의 이름
- srcPos : 복사할 배열의 첫 위치
- dest : 복사 붙여넣을 대상 배열의 이름
- destPos : 복사해서 대상 배열에 붙여 넣기를 시작할 첫 번째 위치
- length : src 에서 dest로 자료를 복사할 요소 개수
public class ArrayCopy { public static void main(String[] args) { int[] arr1 = {10, 20, 30, 40, 50}; int[] arr2 = {1, 2, 3, 4, 5}; System.arraycopy(arr1, 0, arr2, 1, 4); //arr2의 인덱스 1번부터 src의 0번 부터 4개의 요소를 복붙합니다 System.out.println("arr2 = " + Arrays.toString(arr2)); //arr2 = [1, 10, 20, 30, 40] } }
- 객체 배열의 복사
<주의>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("태백1", "상준1"); bookArray1[2] = new Book("태백2", "상준2"); System.arraycopy(bookArray1, 0, bookArray2, 0, 3); //arr1 의 0부터의 값을 arr2 에 0부터 arr1의 0부터의 3개의 값 복사 System.out.println("bookArray2 = " + Arrays.toString(bookArray2)); } } //출력 bookArray2 = [Book{bookName='태백', author='상준'}, Book{bookName='태백1', author='상준1'}, Book{bookName='태백2', author='상준2'}]
- 분명히 bookArray2 배열의 인스턴스를 따로 만들지 않았는데(new 하지 않음) 어떻게 bookArray에 해당 값이 반영된걸까??
얕은복사
- 객체 배열을 복사할 때 인스턴스를 따로 생성하는 것이 아니라 기존 인스턴스의 주소 값만 복사!
- 그러므로 두 객체 배열은 같은 인스턴스를 가리키고 있음!
- 하나의 인스턴스가 변경된다면 다른 객체 배열의 인스턴도 같은 주소를 가리키기에 다른 객체 배열도 영향을 받습니다
깊은복사
- System.arraycopy() 는 얕은 복사로 항상 인스턴스의 주소가 복사됨
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("태백1", "상준1"); bookArray1[2] = new Book("태백2", "상준2"); bookArray2[0] = new Book(); bookArray2[1] = new Book(); bookArray2[2] = new Book(); for (int i = 0; i < bookArray1.length; i++) { bookArray2[i].setBookName(bookArray1[i].getBookName()); bookArray2[i].setAuthor(bookArray1[i].getAuthor()); } //이렇게 직접 인스턴스를 직접 생성후 복사할 배열의 값을 직접 붙여넣어야합니다. System.out.println("bookArray2 = " + Arrays.toString(bookArray2)); bookArray1[0].setBookName("바뀜!"); bookArray1[0].setBookName("바뀐 작성자"); System.out.println("bookArray1 = " + Arrays.toString(bookArray1)); System.out.println("bookArray2 = " + Arrays.toString(bookArray2)); } } // bookArray2 = [Book{bookName='태백', author='상준'}, Book{bookName='태백1', author='상준1'}, Book{bookName='태백2', author='상준2'}] bookArray1 = [Book{bookName='바뀐 작성자', author='상준'}, Book{bookName='태백1', author='상준1'}, Book{bookName='태백2', author='상준2'}] bookArray2 = [Book{bookName='태백', author='상준'}, Book{bookName='태백1', author='상준1'}, Book{bookName='태백2', author='상준2'}]
- arr2 에서 arr1 인스턴스의 변경점에 영향을 받지 않는 것을 확인가능하다.
- 향상된 for 문과 배열
- 배열 요소 값을 순서대로 하나씩 가져와서 변수에 대입
public class EnhancedForLoop { public static void main(String[] args) { String[] strings = {"자바,","안드로이드", "C", "Javascript", "Python"}; System.out.println("========================"); for (String str : strings) { System.out.println("str = " + str); } } } //str = 자바 str = 안드로이드 str = C str = Javascript str = Python
- 배열 요소 값을 순서대로 하나씩 가져와서 변수에 대입
- 분명히 bookArray2 배열의 인스턴스를 따로 만들지 않았는데(new 하지 않음) 어떻게 bookArray에 해당 값이 반영된걸까??
- System.arraycopy(src,srcPos,dest,destPos,length)
- 인덱스 연산자[]
07.2 다차원 배열
- 다차원 배열이란?
- 이차원 이상으로 구현한 배열
- 이차원 배열
int[][]arr = new int[2][3]; 자료형 배열이름 행개수 열개수
알파벳 소문자를 2글자씩 13줄(13행 2열)로 출력
public class EnhancedForLoop { public static void main(String[] args) { char[][] alpha = new char[13][2]; alpha[0][0] = 'a'; alpha[0][1] = 'b'; for (int i = 1; i < alpha.length; i++) { for (int j = 0; j < alpha[i].length; j++) { alpha[i][j] = (char) (alpha[i - 1][j] + 2); } } System.out.println("alpha = " + Arrays.deepToString(alpha)); System.out.println("========================"); for (int i = 0; i < alpha.length; i++) { for (int j = 0; j < alpha[i].length; j++) { System.out.print(alpha[i][j]); } System.out.println(); } } }
07.3 ArrayList 클래스 사용하기
- 기존 배열의 단점과 ArrayList
- 배열을 사용하는 중에는 배열 길이 변경이 어렵다는 단점 존재
- ArrayList의 경우 가변적임!
- ArrayList 의 주요 메서드
메서드 설명 boolean add(E e) 요소 하나를 배열에 추가합니다. E는 요소의 자료형을 의미 int size() 배열에 추가된 요소 전체 개수 반환 E get(int index) 배열의 index 위치에 있는 요소 값을 반환 E remove(int index) 배열의 index 위치에 있는 요소 값을 제거하고 그 값을 반환 boolean isEmpty() 배열이 비어 있는지 확인
- ArrayList 사용법
public class ArrayListTest { public static void main(String[] args) { ArrayList<Book> books = new ArrayList<>(); //ArrayList의 선언 : 제네릭의 경우 자바 6에는 필수적으로 사용해야했음 books.add(new Book("11", "11")); books.add(new Book("11", "11")); books.add(new Book("11", "11")); books.add(new Book("11", "11")); books.add(new Book("11", "11")); books.add(new Book("11", "11")); System.out.println("books = " + books); for (Book book : books) { System.out.println("book = " + book); } } } //books = [Book{bookName='11', author='11'}, Book{bookName='11', author='11'}, Book{bookName='11', author='11'}, Book{bookName='11', author='11'}, Book{bookName='11', author='11'}, Book{bookName='11', author='11'}] book = Book{bookName='11', author='11'} book = Book{bookName='11', author='11'} book = Book{bookName='11', author='11'} book = Book{bookName='11', author='11'} book = Book{bookName='11', author='11'} book = Book{bookName='11', author='11'} arr.get(0) 이런식으로 해당 index =0 의 값을 가져올 수도 있음
07.4 배열 응용 프로그램
- 학생 성적 출력 프로그램의 구현
- Student 클래스 구현
public class Student { int studentID; String studentName; ArrayList<Subject> subjectArrayList; //ArrayList의 선언 > 수강하는 과목은 여러개 이므로.! public Student(int studentID, String studentName) { this.studentID = studentID; this.studentName = studentName; subjectArrayList = new ArrayList<>(); } public void addSubject(String name, int score) { Subject subject = new Subject(); //Subject생성 subject.setName(name); subject.setScorePoint(score); subjectArrayList.add(subject); //배열에 저장 } public void showStudentInfo() { int total = 0; for (Subject s : subjectArrayList) { total += s.getScorePoint(); System.out.println(" 학생 " + studentName + "의 " + s.getName() + "과목 성적은" + s.getScorePoint() + " 점 입니다."); } System.out.println("총점은 : " + total); } }
- Subject 클래스의 구현
public class Subject { //멤버변수 2개! 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; } }
- 테스트 클래스 구현 후 결과 확인
public class StudentTest { public static void main(String[] args) { Student student1 = new Student(1001, "park"); student1.addSubject("국어", 99); student1.addSubject("코딩", 99); Student student = new Student(1002, "lee"); student.addSubject("국어", 23); student.addSubject("코딩", 43); student.addSubject("과학", 45); Student student2 = new Student(1003, "kk"); student2.addSubject("국어", 1); student2.addSubject("코딩", 34); student.showStudentInfo(); System.out.println("========================"); student1.showStudentInfo(); System.out.println("========================"); student2.showStudentInfo(); } } --- 학생 lee의 국어과목 성적은23 점 입니다. 학생 lee의 코딩과목 성적은43 점 입니다. 학생 lee의 과학과목 성적은45 점 입니다. 총점은 : 111 ======================== 학생 park의 국어과목 성적은99 점 입니다. 학생 park의 코딩과목 성적은99 점 입니다. 총점은 : 198 ======================== 학생 kk의 국어과목 성적은1 점 입니다. 학생 kk의 코딩과목 성적은34 점 입니다. 총점은 : 35 종료 코드 0(으)로 완료된 프로세스
- Student 클래스 구현
- 배열은
같은
자료형을 순서대로 관리할 때 사용하는 자료 구조입니다
- 알파벳 출력 예제 소 > 대문자 변환
public class EnhancedForLoop { public static void main(String[] args) { char[][] alpha = new char[13][2]; alpha[0][0] = 'A'; alpha[0][1] = 'B'; for (int i = 1; i < alpha.length; i++) { for (int j = 0; j < alpha[i].length; j++) { alpha[i][j] = (char) (alpha[i - 1][j] + 2); } } System.out.println("alpha = " + Arrays.deepToString(alpha)); System.out.println("========================"); for (int i = 0; i < alpha.length; i++) { for (int j = 0; j < alpha[i].length; j++) { System.out.print(alpha[i][j]); } System.out.println(); } } }
- 배열 길이가 5인 정수형 배열 선언 > 1~10 중 짝수 배열 저장 ,합 출력
class TestMe { public static void main(String[] args) { int[] arr = new int[5]; int count = 0; int sum = 0; for (int i = 1; i < 11; i++) { if (i % 2 == 0) { sum += i; arr[count] = i; count++; } } System.out.println("sum = " + sum); System.out.println("arr = " + Arrays.toString(arr)); } }
- Dog 클래스
public class Dog { private String name; private String type; public Dog(String name, String type) { this.name = name; this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", type='" + type + '\'' + '}'; } } class TestMe2 { public static void main(String[] args) { Dog[] dogs = new Dog[5]; for (int i = 0; i < dogs.length; i++) { dogs[i] = new Dog(i + "", i + ""); } System.out.println("dogs = " + Arrays.toString(dogs)); } } // dogs = [Dog{name='0', type='0'}, Dog{name='1', type='1'}, Dog{name='2', type='2'}, Dog{name='3', type='3'}, Dog{name='4', type='4'}]
- DogTestArray 만들기
class DogTestArray { public static void main(String[] args) { ArrayList<Dog> dogs = new ArrayList<>(); for (int i = 0; i < 5; i++) { dogs.add(new Dog(i + "", i + "")); } System.out.println("dogs = " + dogs); } }