[JAVA] 배열(Array) 정리 - (1)

DongGyu Jung·2022년 1월 6일
4

자바(JAVA)

목록 보기
6/60
post-thumbnail

🏃‍♂️ 들어가기 앞서..

본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕

*해당 교재의 목차 순서와 구성 내용을 기준으로 작성하며
부족할 수 있는 내용은 추가적인 검색을 통해 채워나갈 예정입니다.



📕 배열 (Array)

※ 배열 (Array)
: 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것

배열을 사용할 때
가장 중요한 것은 위에 강조되어 있다시피
" 같은 타입(Type) "이다.

예를 들어, 중간고사 성적 을 저장하려할 때,
과목별로 변수를 선언하기엔 너무 비효율적일 것이다.
그럴 때 한 번에 배열로 만들어서 간단하게 처리할 수 있다.

int score1, score2, score3, score4, score5

int[] score = new int[5] // 점수가 더 많아지더라도 그냥 숫자(길이)만 수정하면 된다.
// score[0] ~ score[4]까지 모두 5개의 저장공간 생성

◎ 선언 & 생성

선언하는 방법은 간단하다.
타입[] 변수이름 ;】 의 형식과
타입 변수이름 [];】 의 형식으로 선언이 가능하다.

배열을 선언하는 것은
배열을 다루기 위한 참조변수를 위한 공간만 만들어지는 것이고

정말 값이 저장되는 공간이 만들어주기 위해서는
선언한 배열을 생성해주어야 한다. ▶ 【(배열변수) = new (타입) [ (길이) ]

int[] score ;
score = new int[5] ;

String[] sub ;
sub = new String[5] ;

◎ 인덱스

  • 요소(element) : " 배열의 각 저장공간 "
  • 인덱스(index) : " 배열의 요소마다 붙여진 일련번호/주소 "

배열을 사용할 때,
값을 저장하고 읽어오는 작업들은
변수의 경우와 다를 것은 없지만
변수 이름이 아닌 배열이름[(인덱스)] 형식을 사용한다.

score[3] = 100 ; // score 배열의 4번째 요소의 값 "저장"

int value = score[3] ; // 앞서 저장된 4번째 요소의 값을 다른 변수에 "대입"

◎ 길이 (feat. .length)

자바에서는 자바 가성머신 (JVM)이 모든 배열의 길이를 별도로 관리한다.
이 길이 정보를 얻기 위해서는 (배열이름).length 를 사용해야 한다.

배열은 한번 생성하면 길이를 변경할 수 없는 상수이기 때문에
수정할 경우,
new로 재선언 해주어야 한다.

int[] score = new int[6];
System.out.println(score[5]) // score[5] 값 출력
System.out.println(score[score.length-1]) //  score[5] 값 출력

int[] score = new int[5];
System.out.println(score[5]) // 에러 : ArrayIndexOutOfBoundsException_배열의 index가 유효 범위를 벗어남
System.out.println(score[score.length-1]) // score[4] 출력

위 설명처럼 배열의 길이를 별도로 관리하기 때문에
배열의 길이와 관련된 실행 코드를 작성할 때,
직접 정수값을 사용하기보단
.length를 사용하는 것이 효율적이다.
(수정할 때마다 유동적으로 반영이 됨.)

◎ 초기화

처음 배열을 생성할 땐,
자동적으로 기본값(0)이 할당되는데

0이라는 값이 할당된 것이기 때문에
각 요소에 원하는 값을 지정해줘야 한다.

만약 배열의 길이가 길고
들어가는 값들의 규칙이 있다면
반복문을 사용하는 것이 효율적이다.

int[] score = new int[5];
score[0] = 50 ;
score[1] = 60 ;
score[2] = 70 ;
score[3] = 80 ;
score[4] = 90 ;

//반복문 활용
int[] score = new int[5];
for (int i = 0 ; i < score.length ; i++) {
    score[i] = i *10 +50
}

또한 생성함과 동시에
길이 작성 없이 값만으로 배열을 생성하는 간단한 방법이 있다.

//값의 개수에 의해 배열의 길이 자동 결정
int[] score = new int[]{ 50, 60, 70, 80, 90 }; //[] 안에 길이를 작성하지 않아도됨
/*
new를 제외해도 가능하다.
단, 선언과 생성을 분리해서 이 방식으로 생성할 경우 오류 발생
*/
// 1
int[] score = { 50, 60, 70, 80, 90 }; // 가능
// 2
score = new int[]{ 50, 60, 70, 80, 90 }; // 가능
/*---------------------------------------------------*/
// 에러
int[] score; //선언 분리
score = { 50, 60, 70, 80, 90 };

◎ 출력

배열에 저장된 값을 확인할 때
반복문을 사용하면 편리하다.
반복문을 사용할 때, 유의할 점은
println()은 줄마다 한 값이 출력되다보니 보기 불편할 수 있다는 점이다.
( print( (값) + "," ) 등의 방법을 사용하자.

int[] score = { 50, 60, 70, 80, 90 };

for (int i = 0 ; i < score.length ; i++) {
    System.out.println(score[i]) ; // 줄마다 값 출력
}

for (int i = 0 ; i < score.length-1 ; i++) {
    System.out.print(score[i] + ",") ; // 쉼표로 구분해서 출력 _ But 마지막 값을 출력하고도 쉼표가 출력됨...
}
System.out.println(score[score.length -1]) //위 But에 대한 해결책

더 간단한 방법이 있(긴 하지만 넘어가자.)..다.
바로 Arrays.toString([배열이름])메서드 이다.

배열의 모든 요소를 문자열로 만들어서 반환하는 기능을 가지고 있다.

import java.util.Arrays 추가해야 사용 가능하다.
출력 형식 : [ (요소1), (요소2), (요소3),... ] 의 형식


문득...
" 찌질(?)하게 무슨 메서드야! 그냥 출력 질러!! "라는 생각이 들어
바로 배열 참조 변수를 출력하게 된다면
이상한 ' (타입)@(주소) ' 형식의 값이 출력될 것이다.
(* 이상한 출력값 예시 : [I@13426bb 심지어 또 바뀔 수 있음..)

하지만 !!
예외적으로
char 배열은 참조변수를 println()메서드로 출력하면
각 요소가 구분자 없이 붙어서 일렬로 그대로 출력된다.
( 우리가 못바꾼다...처음부터 println()메서드가 char 배열일 때만 이렇게 출력되도록 작성되었다.. )

int[] iArr1 = new int[10] ;
int[] iArr2 = new int[10] ;
int[] iArr3 = new int[]{100, 95, 80, 70, 60} ;
//int[] iArr3 = {100, 95, 80, 70, 60} ; //위와 같은 형식의 배열 생성 방법
char[] chArr = {'a', 'b', 'c', 'd'} ;

for (int i = 0; i < iArr1.length ; i++) {
    iArr1[i] = i+1 ;// 1~10 채우기
}
for (int i = 0; i < iArr2.length ; i++) {
    iArr2[i] = (int)(Math.random()*10 + 1) ; // 1~10 범위내 난수 채우기 _ 0.0일 경우 대비 +1
}

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

System.out.println(Arrays.toString(iArr2)) ;
System.out.println(Arrays.toString(iArr3)) ;
System.out.println(Arrays.toString(chArr)) ;
System.out.println(chArr) ;
System.out.println(iArr3) ;

// for문으로 출력
1,2,3,4,5,6,7,8,9,10, // 앞서 설명했던 코드에서처럼 ','가 필요없이 하나 더 출력됨

// Arrays.toString() 메서드
[2, 6, 3, 6, 7, 5, 3, 4, 9, 7]
[100, 95, 80, 70, 60]
[a, b, c, d]

abcd // char배열만 println했을 때 이어서 출력됨
[I@4554617c // 배열 참조 변수 출력 참사

Process finished with exit code 0

{ 활용 }

① 총합 & 평균

: .length 활용 & (float)형 변환 활용

  • 배열 내 값들의 평균을 구할 때, 값의 갯수(배열).length와 동일하다.
  • 평균값이 소숫점일 경우를 대비해서 총합과 length값을 나눌때 length 앞에 (float)로 형변환 해준다.
int sum = 0;
float average = 0f ; // 실수값 평균을 담을 경우 대비, float형으로 선언
int[] score = {100, 93, 99, 100, 100};
for (int i = 0 ; i < score.length; i++) {
    sum += score[i];
}
average = sum / (float)score.length; // 정확한 계산 결과를 위한 실수형으로 형변환

② 최대값 & 최솟값

: for문으로 배열 초기값을 시작으로 하나씩 비교하는 방법

int[] score = {74, 83, 99, 64, 100, 95};

int max = score[0],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) ;

③ 섞기 (Shuffle)

: 기존의 배열 요소들의 순서를 무작위로 바꾸는 작업

  • Math.random() 활용
  • 위 최댓값 최솟값의 코드와 다르게 임의의 인덱스값으로만 n을 사용하기 때문에 for문 안에 선언해서 효율성을 높입니다.
int[] nArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
System.out.println(Arrays.toString(nArr));

for (int i = 0; i < 100; i++) { // 100번 반복해서 섞겠다는 의지....!!
    int n = (int) (Math.random() * 10); // 0이상 1미만의 범위 -> 10 곱해서 0~9 정수 범위 무작위 추출
    // 값 교환은 이전 정리글 참고
    int tmp = nArr[0]; // 첫번째 값은 임시로 tmp에 담아놓기
    nArr[0] = nArr[n]; // 무작위로 뽑은 주소의 값을 배열 첫번째로 위치 이동
    nArr[n] = tmp; // 그 무작위로 뽑은 주소에 배열 첫번재였던 값으로 바꾸기(채워넣기)
}
System.out.println(Arrays.toString(nArr));

④ 로또 번호

: 위 Shuffle의 예제와 비슷하게 값 교환을 통해 작업

  • 배열 전체에서 무작위로 뽑는 형식이 아닌 섞은 후에 앞에서부터 첫번째부터 여섯번째 값까지 가져오는 방식
int[] nBall = new int[45]; // 뽑은 번호공의 의미로 45개의 공들(1~45 배열) 만들기

// 45개의 공들에 1~45 값들을 각각 저장
for (int i = 0; i < nBall.length; i++) { // 100번 반복해서 섞겠다는 의지....!!
    nBall[i] = i + 1;
}
int tmp = 0 ; // 두 값을 바꿀 때 사용할 임시 저장 수단
int j = 0 ; // 무작위 추첨할 공 index 값 (임의)

for (int i = 0; i < 6; i ++){ // 앞 6개 값만 45개중 무작위로 뽑아와서 교체하기
    j = (int)(Math.random() * 45) ; // <<index>> 0~44 범위의 무작위 값
    tmp = nBall[i] ;
    nBall[i] = nBall[j] ;
    nBall[j] = tmp ;
}
for (int i = 0; i < 6; i++){
    System.out.printf("%d 번째 추첨공 숫자는 %d 입니다! %n", i+1 , nBall[i]);
}

1 번째 추첨공 숫자는 17 입니다! 
2 번째 추첨공 숫자는 41 입니다! 
3 번째 추첨공 숫자는 15 입니다! 
4 번째 추첨공 숫자는 27 입니다! 
5 번째 추첨공 숫자는 9 입니다! 
6 번째 추첨공 숫자는 37 입니다! 

※ String 배열

사실 위 [ 배열 ]의 내용과 다를 것 없다.
그저 가독성을 위해 조금 큰 범주로 분리시켰다.

◎ 선언 & 생성

형식은 앞서 배운 배열의 선언, 생성 형식과 동일하다.
이름에만 조금 변화가 생겼다.

String[] (이름) = new String[ (길이) ]; 형식이고
기본값이 앞선 int배열의 기본값 0과는 다르게 'null'이다.


변수 타입에 따른 기본값

종류기본값
Booleanfalse
char\u0000
byte/short/int0
long0L
float0.0f
double0.0d 혹은 0.0
참조형null


◎ 초기화

초기화 역시..!!
int배열과 동일하다.

String[] sub = new String[3] ;
sub[0] = "Korean";
sub[1] = "Math";
sub[2] = "Science";

String[] sub = new String[] {"Korean", "Math", "Science"};

String[] sub = {"Korean", "Math", "Science"};

원래 String클래스이라 new String()을 통해 객체를 생성해야하지만
특별히 이 String클래스만 큰 따옴표("")만으로 간략히 표현하는 것이 허용된다.



🔨 " char배열 <<< String 클래스 ??"

사실 지금까지 우리는
여러 문자가 나열되어 있는,
즉 문자열을 저장할 때 String타입 변수를 사용해왔는데

방금 언급했지만
여러 문자가 나열되어 있다는 것은
다른 말로 " char배열 "이라고 할 수 있다.

그럼 " char 배열을 사용하는게 더 나은거 아니야? " 라고
생각될 수 있지만
자바에서 char배열이 아닌 String클래스를 사용하는 이유는
이 String클래스가 기본 char배열 기능과 더불어 여러가지 추가 기능이 확장된 것이기 때문이다.

String클래스 = char 배열 + 여러 기능(메서드)

  • 『객체 지향』 개념이 나오기 이전의 언어들은 "데이터"와 "기능"을 따로 다뤘지만
    객체지향언어에서는 "관련된 것들끼리 구분하지 않고" 하나에 묶어(클래스) 다룬다.

  • 《객체지향언어》인 Java ▶ char배열과 그와 관련된 기능들을 함께 묶어서 클래스에 정의
    (C 언어 ▶ 문자열을 char 배열로 다룸)


    String 객체(문자열)읽기만 가능할 뿐 내용 변경이 불가능하다.
    ( 변경 가능한 문자열 : StringBuffer클래스 사용 )


🔨 《String 클래스》 주요 메서드

상당히 많은 문자열 관련 메서드들이 제공되지만
모두 설명하기엔 역부족이기에
가장 기본적인 것 몇 가지만 정리해보자.

메서드(Method)
「(결과 Type) 메서드」
설명
(char) charAt([index])해당 index에 있는 문자 반환
(int) length()문자열 길이 반환
(String) substring([from],[to])문자열에서 해당 범위(from~to)의 문자열 반환
(to는 포함 안됨.)
(boolean) equals(<Object obj>)문자열 내용이 같은지 확인
(같으면 true / 다르면 false)
(char[]) toCharArray()문자열을 문자배열(char[])로 변환해서 반환
  • 4번째의 equals메서드는 대소문자 구분을 하기 때문에
    대소문자 구분 없이 비교할 땐 equalsIgnoreCase()를 사용해야 한다.




🎨 [부록] 커맨드 라인 입력

이전 정리 때부터 봤던 내용인데
" 사용자로부터 값을 입력받을 때 "
우린 보통 Scanner클래스nextLine()메서드나 nextInt()메서드 등을 활용했다.

이번엔 위 방법이 아닌 다른 방법으로 사용자 입력을 받는 방법을 알아볼 것이다.
그 방법은 바로
커맨드 라인을 이용하는 것!

프로그램을 실행할 때
클래스 이름 뒤공백 문자로 구분해서
여러 개의 문자열을 프로그램에 전달할 수 있다.

그럼 커맨드라인에 입력된 문자열은 어디로 어떻게 흘러가느냐!

이 문자열들은
String 배열에 담겨서
해당 클래스main 메서드의 매개변수(args)에 전달된다.

그렇게 된다면
" main 메서드 내 "에서
전달받은 문자열들에 접근할 수 있다.

일단 예제 클래스를 하나 만들어보자.

public class Ex5_7 {
    public static void main(String[] args) {
        System.out.println("Properties : " + args.length +"개");
        
        for (int i = 0; i < args.length; i++) {
            System.out.println("args[" + i + "] = \"" + args[i] + "\"");
        }
    }
}

프로그램을 실행시킬 때
|command line| > java (클래스 이름) 문자열1 문자열2 문자열3 (문자열 자체 내부에 공백이 있으면 큰따옴표로 감싸야함)
이렇게 입력하게 되면

앞서 설명했던 대로 문자열이 전달된다. ( *주의 :숫자를 적더라도 문자열로 인식됨* )

0개의 댓글