같은 타입의 많은 데이터들을 모아 집합시켜 저장한 자료구조
| 데이터 | 100 | 200 | 300 | 400 | 500 |
|---|---|---|---|---|---|
| 인덱스 | 0 | 1 | 2 | 3 | 4 |
// 1 배열 선언 및 초기화
int[] arr = new int[5]; // 배열 선언, 생성
arr[0] = 100; // 데이터 초기화
arr[1] = 200;
arr[2] = 300;
arr[3] = 400;
arr[4] = 500;
// 2 반복문을 이용해 순차적으로 데이터 저장 가능
for(int i = 0; i < arr.length; i++){
arr[i] = i * 100; // arr: [0, 100, 200, 300, 400]
}
// 3 배열 선언과 초기화 동시 진행
int[] arr2 = {100, 200, 300, 400, 500};
int[] arr = {100, 200, 300, 400, 500};
System.out.println(arr); // [I@48140564
// [I: Integer
// @48140564: 주소값
배열 변수의 값은 메모리에 있는 주소값(타입@주소)이다.
int[] arr2 = {100, 200, 300, 400, 500};
// 반복문으로 순회하면서 직접 데이터 출력
for (int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}
// Arrays 클래스를 사용해서 출력
System.out.println(Arrays.toString(arr2));
char[] ch = {'J', 'a', 'v', 'a'};
System.out.println(ch);
String[] str = {"Java", "JavaScript", "Python"};
System.out.println(Arrays.toString(str));
100
200
300
400
500
[100, 200, 300, 400, 500]
Java
[Java, JavaScript, Python]
char 형 배열은 예외인데, 문자 같은 경우 println으로 바로 출력이 가능하다.
데이터 저장 공간이 부족해서 확장하려면 기존에 있던 배열보다 큰 배열을 생성하고 복사해야 한다.
import java.util.Arrays;
class Test1{
public static void main(String[] args) {
int[] arr1 = {100, 200, 300, 400, 500};
int[] arr2 = new int[arr1.length * 2]; // 초기 배열보다 큰 새로운 배열 선언
// 반복문으로 순회하면서 복사
for(int i = 0 ; i < arr1.length ; i++) {
arr2[i] = arr1[i];
}
// 원래의 배열을 가리키고있던 참조변수 arr1이 새로 복사된 arr2 배열을 가리킴.
// arr1은 arr2와 같은 주소 값을 가짐
arr1 = arr2;
}
}
class Test2{
public static void main(String[] args) {
int[] arr1 = {10, 20, 30, 40, 50};
int[] arr2 = new int[arr1.length * 2];
// System.arraycopy() 메서드 사용
// arr1의 index 0부터 arr1.length 전체 길이 만큼 arr2의 index 0 부터 복사함.
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
/*
- 첫번째 인자 : 복사할 배열
- 두번째 인자 : 복사를 시작할 배열의 위치
- 세번째 인자 : 붙여넣을 배열
- 네번째 인자 : 복사된 배열값들이 붙여질 시작위치 (차례대로 붙여 넣어진다)
- 다섯번째 인자 : 지정된 길이만큼 값들이 복사된다.
*/
}
}
import java.util.Arrays;
class Test3{
public static void main(String[] args) {
int[] arr1 = {10, 20, 30, 40, 50};
int[] arr2 = new int[arr1.length * 2];
// Array.copyOf() 메서드 사용
// arr1 배열을 arr1.length 전체 길이만큼 전체 복사해서 arr2에 할당
arr2 = Arrays.copyOf(arr1, arr1.length);
System.out.println(Arrays.toString(arr2)); // [10, 20, 30, 40, 50]
// 배열요소 시작점, 끝점 지정. 1, 2 만 복사해서 반환
int[] arr3 = Arrays.copyOfRange(arr2, 1, 3);
System.out.println(Arrays.toString(arr2)); // [20, 30]
}
}
for문 보다 메서드를 이용하는게 거의 두배 정도로 빠르게 복사한다고 한다
import java.util.Arrays;
import java.util.Collections;
public class study {
public static void main(String[] args) {
int[] arr = { 3,2,0,1,4 };
// Arrays.sort() 메서드 사용
// 오름차순 정렬
Arrays.sort(arr);
System.out.println(Arrays.toString(arr)); // [0, 1, 2, 3, 4]
// 내립차순 정렬
Integer[] arr2 = { 3,2,0,1,4 }; // Wrapper 클래로 선언
Arrays.sort(arr2, Collections.reverseOrder());
System.out.println(Arrays.toString(arr2)); // [4, 3, 2, 1, 0]
// 오름차순 부분 정렬
int[] arr3 = { 3,2,0,1,4 };
Arrays.sort(arr3, 0, 3); // 배열 인덱스 0, 1, 2 부분 정렬
System.out.println(Arrays.toString(arr3)); // [0, 2, 3, 1, 4]
}
}
내림차순 하기 위해 Collections 클래스를 사용하려면 배열을 primitive type이 아니라 Wrapper 클래스로 만들어야 한다.
import java.util.Arrays;
public class study {
public static void main(String[] args) {
String[] arr1 = { "포비", "크롱", "애디", "뽀로로", "루피" };
String[] arr2 = { "포비", "크롱", "애디", "뽀로로", "루피" };
String[] arr3 = { "포비", "크롱", "애디" };
// Arrays.equals 메서드 사용
System.out.println("arr1 == arr2 : " + Arrays.equals(arr1, arr2)); // arr1 == arr2 : true
System.out.println("arr1 == arr3 : " + Arrays.equals(arr1, arr3)); // arr1 == arr3 : false
}
}
이 클래스에는 배열을 조작하는 다양한 방법(예: 정렬 및 검색)이 포함되어 있습니다. 이 클래스에는 배열을 목록으로 볼 수 있는 정적 팩토리도 포함되어 있습니다.
명시된 경우를 제외하고 지정된 배열 참조가 null인 경우 이 클래스의 메소드는 모두 NullPointerException을 던집니다.
특정한 배열에 의해 백업된 고정 크기 List로 반환합니다.
Arrays.asList()는 Arrays의 private 정적 클래스인 ArrayList를 리턴한다.
java.util.ArrayList 클래스와는 다른 클래스이다.
java.util.Arrays.ArrayList 클래스는 set(), get(), contains() 메서드를 가지고 있지만 원소를 추가하는 메서드는 가지고 있지 않기 때문에 사이즈를 바꿀 수 없다.
// 사용 방법
String[] str = { "포비", "크롱", "애디", "뽀로로", "루피" };
List<String> list = Arrays.asList(str);
List<String> list2 = Arrays.asList("포비", "크롱", "애디", "뽀로로", "루피");
List<Integer> list3 = Arrays.asList(1, 2, 3, 4);
Arrays.asList()는 String[] str(특정한 배열)를 백업할 때 주소값을 가져온다
따라서 str 데이터가 변경시키면 list도 변경된다.
String[] str = { "포비", "크롱", "애디", "뽀로로", "루피" };
List<String> list = Arrays.asList(str);
System.out.println("list = " + list);
str[3] = "pororo";
System.out.println("list = " + list);
출력 결과
list = [포비, 크롱, 애디, 뽀로로, 루피]
list = [포비, 크롱, 애디, pororo, 루피]
이진 탐색 알고리즘을 사용해 지정된 배열에서 지정된 값의 위치를 찾습니다.
이 메서드를 호출하기 전에 정렬되어 있어야 합니다. 만약 정렬되지 않았다면 결과값을 찾을 수 없습니다. 만약 배열에 지정된 값이 여러개 포함되어 있다면 정확한 결과값을 보장하지 않습니다.
String[] str = { "포비", "크롱", "애디", "뽀로로", "루피" };
Arrays.sort(str);
int a = Arrays.binarySearch(str, "뽀로로");
System.out.println("뽀로로의 위치: " + a); // 1
System.out.println(Arrays.toString(arr1)); // [루피, 뽀로로, 애디, 크롱, 포비]
키가 없을 때에는 어느 위치에 넣어야 sorting 상태가 유지되는지 찾은 다음에, 그 위치에 -1을 곱하고 1을 빼게 됩니다.
int[] arr = {1, 3, 4, 7, 9};
int b = Arrays.binarySearch(arr, 6); // 6보다 큰 최초의 위치 찾음, Insertion point = 3
System.out.println(b); // -4 (-Insertion point-1)
이진 검색 알고리즘을 사용하여 지정된 값에 대해 지정된 배열 범위를 검색합니다.
범위 지정하는 것만 빼면 나머지는 위 binarySearch와 같다.
복사본이 지정된 길이를 갖도록 자르거나 0으로 패딩하여(필요한 경우) 지정된 배열을 복사합니다.
원본 배열과 복사본 모두에서 유효한 모든 인덱스의 경우 두 배열에 동일한 값이 포함됩니다.
복사본에는 유효하지만 원본에는 없는 인덱스의 경우 복사본에는 0이 포함됩니다. 이러한 인덱스는 지정된 길이가 원본 배열의 길이보다 큰 경우에만 존재합니다.
int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] arr2 = Arrays.copyOf(arr1, arr1.length);
System.out.println(Arrays.toString(arr2));
// 복사본이 원본보다 작을 경우 나머지 값들을 잘라냄
int[] arr3 = Arrays.copyOf(arr1, 7);
System.out.println(Arrays.toString(arr3));
// 복사본이 원본보다 클 경우 나머지 값들을 0으로 채움
int[] arr4 = Arrays.copyOf(arr1, 12);
System.out.println(Arrays.toString(arr4));
출력 결과
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0]
지정된 배열의 지정된 범위를 새 배열로 복사합니다.
범위(from)의 초기 인덱스는 0과 original.length(포함) 사이에 있어야 합니다.
original[from]의 값은 사본의 초기 요소에 배치됩니다.(from == original.length 또는 from == to가 아닌 경우)
원본 배열의 후속 요소 값은 복사본의 후속 요소에 배치됩니다.
범위(to)의 최종 인덱스는 from보다 크거나 같아야 합니다. original.length보다 클 수 있으며, 이 경우 인덱스가 original.length - from보다 크거나 같은 복사본의 모든 요소에 0이 배치됩니다. 반환된 배열의 길이는 to - from입니다.
int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] arr2 = Arrays.copyOfRange(arr1, 5, 10); // 인덱스 5~10까지 복사
System.out.println(Arrays.toString(arr2));
System.out.println("arr2의 길이: " + arr2.length);
int[] arr3 = Arrays.copyOfRange(arr1, 10, 12);
System.out.println(Arrays.toString(arr3));
출력 결과
[6, 7, 8, 9, 10]
arr2의 길이: 5
[0, 0]
arr3의 길이: 2
지정된 두 배열이 서로 완전히 동일한 경우 true를 반환합니다.
equals(Object[],Object[]) 메소드와 달리, 이 메소드는 임의의 깊이로 중첩된 배열과 함께 사용하기에 적합합니다.
두 배열 참조가 null인 경우, 또는 두 배열이 동일한 요소 수를 가지고 있고 두 배열의 해당 요소 쌍이 매우 동일한 경우 완전히 동일한 것으로 간주됩니다.
null 가능성이 있는 요소 e1과 e2는 다음 조건 중 하나라도 해당되면 완전히 동일한 것으로 간주됩니다.
지정된 배열 중 하나라도 직접 또는 간접적으로 1차 이상의 배열을 통해 자신을 요소로 포함하는 경우, 이 메소드의 동작은 정의되지 않습니다.
int[][] arr1 = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};
int[][] arr2 = Arrays.copyOf(arr1, arr1.length);
// e1과 e2가 완전히 같은 경우
boolean isTrue12 = Arrays.deepEquals(arr1, arr2);
System.out.println("isTrue12 = " + isTrue12);
int[][] arr3 = null;
// e1, e2 둘 중 하나가 null 인 경우
boolean isTrue13 = Arrays.deepEquals(arr1, arr3);
System.out.println("isTrue13 = " + isTrue13);
int[][] arr4 = null;
// e1, e2 둘 다 null 인 경우
boolean isTrue34 = Arrays.deepEquals(arr3, arr4);
System.out.println("isTrue34 = " + isTrue34);
int[][] arr5 = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 0}};
// e1과 e2가 완전히 같지 않은 경우
boolean isTrue15 = Arrays.deepEquals(arr1, arr5);
System.out.println("isTrue15 = " + isTrue15);
출력 결과
isTrue12 = true
isTrue13 = false
isTrue34 = true
isTrue15 = false
지정된 배열의 "깊은 내용"을 기반으로 해시 코드를 반환합니다.
이는 배열의 요소 뿐만 아니라 하위 배열이나 그 하위 요소 등을 고려하여 해시 코드를 계산합니다.
하지만 배열 자체가 직접 또는 간접적으로 하나 이상의 배열 요소를 포함하는 경우 이 메소드를 호출하는 것은 허용되지 않습니다. 이러한 호출의 동작은 정의되어 있지 않습니다.
Arrays.deepEquals(a, b)와 같이 두 배열 a와 b가 있다면, Arrays.deepHashCode(a) == Arrays.deepHashCode(b)도 성립합니다.
이 메소드가 반환하는 값의 계산 방법은 List.hashCode()가 동일한 요소를 동일한 순서로 포함하는 리스트에서 반환하는 값과 유사합니다. 단 하나의 차이점은 a의 요소 e가 배열인 경우, e가 기본 타입 배열인 경우는 Arrays.hashCode(e)의 적절한 오버로딩을 호출하여 해시 코드를 계산하고, 참조 타입 배열인 경우는 Arrays.deepHashCode(e)를 재귀적으로 호출하여 계산한다는 것입니다. a가 null인 경우 이 메소드는 0을 반환합니다.
int[][] arr1 = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};
int[][] arr2 = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 0}};
int[][] arr3 = null;
int[][] arr4 = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};
int a = Arrays.deepHashCode(arr1);
int b = Arrays.deepHashCode(arr2);
int c = Arrays.deepHashCode(arr3);
int d = Arrays.deepHashCode(arr4);
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("c = " + c);
System.out.println("d = " + d);
출력 결과
a = 952460998
b = 952460988
c = 0
d = 952460998
지정된 배열의 "깊은 내용"의 문자열 표현을 반환합니다.
배열이 다른 배열을 요소로 포함하는 경우, 문자열 표현에는 해당 배열의 내용 등이 포함됩니다. 이 메서드는 다차원 배열을 문자열로 변환하는 데 사용됩니다.
문자열 표현은 대괄호 ("[]")로 묶인 배열 요소의 목록으로 구성됩니다. 인접한 요소는 ", " (쉼표와 공백) 문자로 구분됩니다. 요소는 String.valueOf(Object)에 의해 문자열로 변환됩니다. 그러나 요소가 배열이면 재귀적으로 이 메서드가 호출됩니다.
요소 e가 기본 타입의 배열인 경우, Arrays.toString(e)의 적절한 오버로딩을 호출하여 문자열로 변환됩니다. 요소 e가 참조 타입의 배열인 경우, 이 메서드가 재귀적으로 호출됩니다.
만약 지정된 배열이 자체를 요소로 포함하거나 1차 이상의 배열을 통해 간접적으로 자체에 대한 참조가 포함되어 있으면 무한 재귀를 방지하기 위해 자체 참조는 "[...]" 문자열로 변환됩니다. 예를 들어, 자신에 대한 참조만 포함하는 배열은 "[[...]]"로 렌더링됩니다.
이 메서드는 지정된 배열이 null인 경우 "null"을 반환합니다.
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
String[][] arr = {{"포비", "크롱", "애디"}, {"루피", "뽀로로"}};
String string = Arrays.deepToString(arr);
System.out.println("string = " + string);
Student[][] students = {
{
new Student("kim", 20),
new Student("park", 16),
new Student("lee", 24)
},
{
new Student("choi", 27),
new Student("jin", 35)
}
};
String student = Arrays.deepToString(students);
System.out.println("student = " + student);
}
}
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
출력 결과
string = [[포비, 크롱, 애디], [루피, 뽀로로]]
student = [[dataStructure.array.Student@6aaa5eb0, dataStructure.array.Student@3498ed, dataStructure.array.Student@1a407d53], [dataStructure.array.Student@5ebec15, dataStructure.array.Student@21bcffb5]]
지정된 두 배열이 서로 같으면 true를 반환합니다.
두 배열이 같은 경우는 두 배열이 모두 동일한 수의 요소를 포함하고 두 배열의 모든 해당 요소 쌍이 같은 경우입니다. 즉, 두 배열이 동일한 요소를 동일한 순서로 포함하는 경우 두 배열이 같습니다. 또한, 두 배열 참조가 모두 null인 경우에도 같다고 간주합니다.
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = {1, 2, 3, 4, 5};
boolean isTrue12 = Arrays.equals(arr1, arr2);
System.out.println("isTrue12 = " + isTrue12);
출력 결과
isTrue12 = true
지정된 배열의 각 요소에 지정된 값을 할당합니다.
int[] arr1 = {1, 2, 3, 4, 5};
System.out.println(Arrays.toString(arr1));
Arrays.fill(arr1, 0);
System.out.println(Arrays.toString(arr1));
출력 결과
[1, 2, 3, 4, 5]
[0, 0, 0, 0, 0]
지정된 배열의 지정된 범위의 각 요소에 지정된 값을 할당합니다.
채울 범위는 fromIndex(포함)에서 toIndex(제외)까지입니다. (fromIndex==toIndex인 경우, 채울 범위는 비어 있습니다.)
int[] arr1 = {1, 2, 3, 4, 5};
System.out.println(Arrays.toString(arr1));
Arrays.fill(arr1, 1, 4, 0);
System.out.println(Arrays.toString(arr1));
Arrays.fill(arr1, 3, 3, 9);
System.out.println(Arrays.toString(arr1));
출력 결과
[1, 2, 3, 4, 5]
[1, 0, 0, 0, 5]
[1, 0, 0, 0, 5]
지정된 배열의 내용을 기반으로 해시 코드를 반환합니다.
Arrays.equals(a, b)와 같은 두 개의 null이 아닌 배열 a 및 b의 경우 Arrays.hashCode(a) == Arrays.hashCode(b)인 경우도 있습니다.
이 메서드가 반환하는 값은 a의 요소를 같은 순서로 나타내는 일련의 a와 같은 타입의 인스턴스를 포함하는 List에서 hashCode 메서드를 호출하여 얻을 수 있는 값과 동일합니다. a가 null이면 이 메서드는 0을 반환합니다.
int[] a = {1, 2, 3, 4, 5};
int[] b = {1, 2, 3, 4, 5};
// a와 b가 같은 내용을 갖고 있는지 비교
boolean equals = Arrays.equals(a, b);
System.out.println("equals = " + equals);
// a와 b의 해시 코드 값 비교
int aHashCode = Arrays.hashCode(a);
int bHashCode = Arrays.hashCode(b);
System.out.println("aHashCode = " + aHashCode);
System.out.println("bHashCode = " + bHashCode);
// a와 같은 내용의 Integer 인스턴스 시퀀스를 갖는 List의 해시 코드 값 비교
List<Integer> aList = Arrays.asList(1, 2, 3, 4, 5);
int aListHashCode = aList.hashCode();
System.out.println("aListHashCode = " + aListHashCode);
주어진 배열의 각 요소를 제자리에 병렬로 누적합니다.
예를 들어 배열이 처음에 [2, 1, 0, 3]을 보유하고 연산이 더하기를 수행하는 경우 반환 시 배열은 [2, 3, 3, 6]을 보유합니다. 병렬 누적 계산은 일반적으로 다차원 배열에 대해서 순차 루프보다 더 효율적입니다.
// 병렬로 배열의 각 요소에 대해 누적 합을 계산하는 방법
int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Arrays.parallelPrefix(a, (x, y) -> x + y);
System.out.println("a = " + Arrays.toString(a));
// 순차적으로 배열의 각 요소에 대해 누적 합을 계산하는 방법
int[] b = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int i = 1; i < b.length; i++) {
b[i] = b[i] + b[i - 1];
}
System.out.println("b = " + Arrays.toString(b));
a = [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
b = [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
제공된 generator 함수를 사용하여 지정된 배열의 모든 요소를 병렬로 설정하여 각 요소를 계산합니다.
generator 함수에서 예외가 발생하면 parallelSetAll에서 확인되지 않은 예외가 발생하고 배열은 불확실한 상태로 남습니다.
int[] arr = new int[10];
// 병렬로 generator 함수를 사용하여 배열 요소를 설정하는 방법
Arrays.parallelSetAll(arr, i -> i * i);
System.out.println("Parallel setAll: " + Arrays.toString(arr));
Parallel setAll: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
해당 요소의 자연적인 순서에 따라 지정된 개체 배열을 오름차순으로 정렬합니다.
메서드를 호출할 때, 배열의 모든 요소는 Comparable 인터페이스를 구현해야 하며 상호 비교 가능해야 합니다. 이는 e1.compareTo(e2)가 배열의 모든 요소 e1과 e2에 대해 ClassCastException을 던지지 않아야 함을 의미합니다.
int[] arr = new int[10];
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(10);
}
System.out.println("Sort Before: " + Arrays.toString(arr));
Arrays.parallelSort(arr);
System.out.println("Sort After: " + Arrays.toString(arr));
출력 결과
Sort Before: [4, 4, 6, 8, 4, 9, 3, 0, 8, 3]
Sort After: [0, 3, 3, 4, 4, 4, 6, 8, 8, 9]
지정된 배열의 모든 요소를 지정된 generator 함수를 사용하여 계산한 후 설정합니다.
generator 함수가 예외를 throw하는 경우, 예외는 호출자에게 중계되고 배열은 불확정한 상태로 유지됩니다.
int[] arr = new int[5];
Arrays.setAll(arr, i -> i * 2);
System.out.println(Arrays.toString(arr));
출력 결과
[0, 2, 4, 6, 8]
이 메서드는 지정된 배열을 오름차순으로 정렬합니다.
구현 참고: 이 정렬 알고리즘은 Vladimir Yaroslavskiy, Jon Bentley 및 Joshua Bloch에 의해 개발된 이중 피벗 퀵소트(Dual-Pivot Quicksort)입니다. 이 알고리즘은 다른 퀵소트가 제곱 시간 복잡도에 빠지는 많은 데이터 집합에서 O(n log(n)) 성능을 제공하며, 전통적인 (단일 피벗) 퀵소트 구현보다 일반적으로 더 빠릅니다.
int[] arr = {5, 2, 8, 4, 7};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
출력 결과
[2, 4, 5, 7, 8]
참고
Inpa Dev - [JAVA] ☕ 배열(Array) 완벽 다루기 가이드
Hello_Worker - [Java] Ch05_1. 배열(Array)
Java™ Platform Standard Ed. 8 - Class Arrays
테코블 - new ArrayList<>() vs Arrays.asList()