-
[Java] 배열, 향상된 for문언어/Java 2024. 10. 28. 12:20
[지금 무료]김영한의 자바 입문 - 코드로 시작하는 자바 첫걸음 강의 | 김영한 - 인프런
김영한 | 프로그래밍에 처음 입문하는 분들을 위한 자바 강의입니다. 코드를 따라하면서 손쉽게 자바를 배울 수 있습니다., 국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 자바 입문[사
www.inflearn.com
아래 내용의 출저는 위 강의에서 가지고 왔으며, 더욱 자세하게 보실 수 있습니다.
오늘의 단축키 Tip
향상된 for문을 사용하고 싶을 때
iter섹션 8 - 문제와 풀이 4
package scanner.ex; import java.util.Scanner; public class ScannerWhileEx3 { public static void main(String[] args) { Scanner input = new Scanner(System.in); int sum = 0; int cnt = 0; int num = 0; System.out.print("숫자를 입력하세요. 입력을 중단하려면 -1을 입력하세요 : "); while ((num = input.nextInt()) != -1) { cnt++; sum += num; } System.out.println("입력한 숫자들의 합계 : " + sum); System.out.println("입력한 숫자들의 평균 : " + (double)sum / cnt); } }
- 위 소스 코드에서 while문을 원래 배운 대로 라면 아래와 같다.
while (true) { if (num == -1){ break; } }
- 위 코드를 간결하게 while ((num = input.nextInt()) != -1) 로 바꾸어 줄 수 있다. 즉, 축약이 가능하다.
배열
int[] students;
- int a; 에는 int 형 변수를 담을 수 있는 것 처럼
- int[] students 도 int 배열을 students 에 담을 수 있다.
- 이 때 students는 배열을 가리키는 참조값을 생성한다.
- 이 때는 참조 변수만큼만 메모리에 공간을 차지한다. 32JVM 에서는 4바이트 64JVM 에서는 8바이트
- 주소 공간
- 32비트 시스템 : 메모리 주소를 32비트로 표현 하므로 2**32 (약 4GB)의 메모리 주소를 사용할 수 있다.
- 64비트 시스템 : 2**64 메모리의 주소를 사용할 수 있다.
- 참조 변수의 크기
- 32 비트 시스템 : 참조 변수의 크기는 4바이트. 즉, 배열이나 객체의 주소를 4바이트로 저장한다.
- PT형 말로는 그 크기를 직접 확인하고 싶은 데 그럴 수는 없다고 한다.
- 32 비트 시스템 : 참조 변수의 크기는 4바이트. 즉, 배열이나 객체의 주소를 4바이트로 저장한다.
- 주소 공간
students = new int[5];
int[] students = new int[5]; // 배열 생성 int[] students = x001; // new int[5]의 결과로 x001 참조값 반환
- 총 5개의 int 형 변수를 생성한다.
- 자바는 배열을 생성할 때, 그 내부값을 자동으로 초기화 한다.
- int형은 0
- String은 null
- boolean 은 false
- new int[5] 자체에는 아무런 이름이 없다. 다시 말해 연속적으로 5개의 공간만 비워둔 상태
- 따라서 생성한 배열에 접근하는 방법이 필요하다.
- 배열을 생성할 때 참조값을 어딘가에 보관해두어야 한다.
- 여기서는 `students 라는 변수를 통해 이 배열에 접근할 수 있다.
- 동적으로 어떻게 넣어줄까?
int[] students = new int[5]; // 배열 생성 int[] students = x001; // new int[5]의 결과로 x001 참조값 반환
1차원 배열 리팩토링
int[] students = new int[]{90. 80, 70, 60, 50}; // 위 소스 코드와 아래는 같다. int[] students = {90, 80,30, 60, 50};
- 주의할 점은 선언과 동시에 초기화를 해야 작동한다. 그 이유는 new 키워드 없이 배열을 직접 할당하는 것은 문법적으로 올바르지 않아서 컴파일 오류가 발생한다.
2차원 배열
int[][] arr = new int[2][3]; arr[행][열], arr[row][clomun]
- 번외
- 2차원 배열에서는 2중 for문으로 2차원 배열에 접근할 때,
- 열 우선 접근 보다 행 우선 접근을 해야 한다.
- 예를 들어
1 2 3 4 5 6
- 위와 같은 2차원 배열이 있다고 하자.
- 메모리상에는 아래와 같이 저장될 것이다.
| 1 | 2 | 3 | 4 | 5 | 6 |
- 열 우선 접근을 하게 된다면, 메모리의 비연속적인 위치에 접근하게 된다. 이 경우 캐시의 효율성이 떨어진다.
- 따라서 행 우선 접근을 해서 첫 번째 루프(행)을 통해 모든 열에 접근하고, (연속적), 나서 다음 행으로 넘어가기 때문에 메모리 캐시 히트가 높아진다. (지역성의 원리 - 공간 지역성이 좋은 예제)
package array; public class ArrayDi3 { public static void main(String[] args) { // 2x3 2차원 배열을 만든다. int[][] arr = { {1,2,3}, {4,5,6} }; //행2, 열3 for (int row = 0; row < arr.length; row++) { for (int column = 0; column < arr[row].length; column++) { System.out.print(arr[row][column] + " "); } System.out.println();//한 행이 끝나면 라인을 변경한다. } } }
- arr.length -> 제일 밖에 있는 괄호 안에 괄호들이 몇개 있는 지 { {}, {} } 2개 있다.
- arr[row].length -> 그 안에 있는 괄호들 안에 원소가 몇개 있는 지 { {1, 2, 3}, {4, 5, 6} } -> 3개
[일반적인 for문]
for (int i = 0; i < numbers.length; i++) { int number = numbers[i]; System.out.println(number); }
- 배열에 있는 값을 순서대로 읽어서 number 변수에 넣고 출력한다.
- 배열은 처음부터 끝까지 순서대로 읽어서 사용하는 경우가 많다.
- 그런데 배열의 값을 읽으려만 int i 와 같은 인덱스를 사용해 탐색할 수 있는 변수를 선언해야 한다.
- 그리고 끝 조건을 지정해야 한다.
- 마지막으로 배열의 값을 하나 읽을 때마다 인덱스를 하나씩 증가해야 한다.
[향상된 for문 - for-each]
for (number : numbers) { sout(number); }
- 실무에서 가장 많이 사용하는 for문
- 단순히 해당 배열을 처음부터 끝까지 탐색한다.
- for(반복할 때마다 찾은 값을 저장할 변수 : 배열)
- 그러면 알아서 numbers[i] 에 값들이 저장된다 !!!!!
- 주의 할점 !
- 인덱스 값이 필요할 때는 당연히 사용할 수 없다.
[문제와 풀이 1 ArrEx2]
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("5개의 정수를 입력하세요:"); int[] arr = new int[5]; for (int i = 0; i < arr.length; i++) { arr[i] = scanner.nextInt(); } System.out.println("출력"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]); if (i < arr.length - 1) { System.out.print(", "); } } }
- 첫 번째 for문에서 arr = scanner.nextInt(); 라고 작성하였다.
- 값을 인덱스에 넣어줄 거기 때문에 arr[i] = scanner.nextInt(); 해주는 게 맞다.
향상된 for문으로 값 넣기는 안된다.
int[] numbers = new int[5]; for (int number : numbers) { number = nextInt(); }
- for-each (향상된 for문)에서 사용되는 변수가 배열의 요소를 참조하는 것이 아니라, 각 요소의 복사본을 다루기 때문이다.
- 위 소스코드에서 number는 numbers 배열의 각 요소의 복사본이다. 즉, number를 변경해도 numbers 배열의 값은 변경되지 않는다.
- 따라서 인덱스를 사용하여 직접 접근해 수정해야 된다.
숫자 사이에 ', ' 넣기
if (i < arr.length - 1){ sout(', ); }
베열과 역순 출력
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int[] arr = new int[5]; System.out.println("5개의 정수를 입력하세요: "); for (int i = 0; i < arr.length; i++) { arr[i] = scanner.nextInt(); } for (int i = arr.length; i < 0; i--) { System.out.println(arr[i]); } }
출력 결과
- intelJ 에서 돌렸을 때 딱히 컴파일은 잘된다.
- 하지만 내가 원한 의도와 다르게 결과값을 출력하는 것을 볼 수 있다.
생각 1
for(int i = arr.length ...)
- arr.len은 현재 5이고 arr의 마지막 인덱스는 4이다. 이 부분에서 인식하지 못해 생긴 오류라고 생각이 든다.
- 따라서 arr.len - 1을 해주었다.
for(int i = arr.length - 1; i < 0; i++)
- 어랏 그래도 출력되지 않았다.
생각 2
for(int i = arr.length; i < 0; i--)
- 위 소스 코드에서 i < 0; 이 잘못되었구나. i는 5, 4, 3,........점진적으로 작아질 텐데... for문이 안끝나겠구나.
- i >= 0 로 종료 조건을 바꾸어 주었더니 해결했다.
'언어 > Java' 카테고리의 다른 글
[Java] 반환타입, 메서드 오버로딩 (0) 2024.10.30 [Java] 메서드 (feat. 인수 != 매개변수) (2) 2024.10.29 [Java] 형 변환, 계산과 형 변환, 스캐너 (0) 2024.10.26 [Java] operator and conditional statement (3) 2024.10.24 [Java] variable (1) 2024.10.23