배열 정렬은 일반적인 작업이지만, 때로는 정렬 후 요소의 원래 인덱스를 알아야 할 때가 있습니다.
배열은 그대로 두고 배열을 정렬했을 때의 순서를 기존 index로 확인하고 싶을 경우 어떻게 하는지 확인해보도록 하겠습니다.
먼저 기본 정보가 다음과 같다고 가정해 보겠습니다.
// 기초 정보
int[] array = {40, 10, 20, 30};
정렬하기 전에 이 배열의 요소의 index는 다음과 같습니다.
- index 0 : 40
- index 1 : 10
- index 2 : 20
- index 3 : 30
이 배열을 정렬한 후, 우리는 요소의 새로운 index를 다음과 같이 얻게 하고 싶습니다.
- index 0 : 10 (기존 index 1)
- index 1 : 20 (기존 index 2)
- index 2 : 30 (기존 index 3)
- index 3 : 40 (기존 index 0)
즉, 배열을 오름차순으로 정렬하였을 경우 index의 변화를 살펴보도록 하겠습니다.
index와 함께 Custom Comparator 활용
정렬된 index를 얻는 방법 중 하나느 배열 요소와 함께 인덱스를 유지하는 Custom Comparator를 사용하는 것입니다.
이 방법을 사용하면 원래 위치를 추적하면서 요소 값을 기준으로 배열을 정렬할 수 있습니다.
@Test
void givenArray_whenUsingCustomComparator_thenSortedIndicesMatchExpected() {
// index array
Integer[] indices = new Integer[array.length];
for (int i = 0; i < array.length; i++) {
indices[i] = i;
}
// array index sort
Arrays.sort(indices, Comparator.comparingInt(i -> array[i]));
assertArrayEquals(new Integer[]{1, 2, 3, 0}, indices);
}
이 예제에서 원래 배열(array)의 index를 보관하기 위해 indices 배열을 초기화하고 각 요소는 배열에서 해당 요소의 index를 나타내고 있습니다.
Array.sort() 메서드와 함께 Custom Comparator를 사용하여 indices 배열이 배열의 값을 기준으로 정렬됨을 알 수 있습니다. 또한 Comparator.comparingInt(i -> array[i])는 해당 index의 배열 값을 기준으로 indices 배열의 요소를 비교합니다.
정렬 후 정렬된 인덱스 배열이 예상 순서([1, 2, 3, 0])와 일치하는지 확인합니다.
Java 8 Stream API 활용
Java 8의 새로운 기능으로 요소 시퀸스를 처리하기 위한 클래스를 포함하는 스트림(java.util.stream)기능을 활용할 것입니다.
원래 배열의 값을 기준으로 index를 얻고 정렬하기 위해 Java 8 Stream API를 활용하는 방법은 다음과 같습니다.
@Test
void givenArray_whenUsingStreamAPI_thenSortedIndicesMatchExpected() {
// index array sort
List<Integer> indices = IntStream.range(0, array.length)
.boxed().sorted(Comparator.comparingInt(i -> array[i])).collect(Collectors.toList());
assertIterableEquals(Arrays.asList(1, 2, 3, 0), indices);
}
이 예제에서는 IntStream.range() 메서드를 사용하여 0에서 array.length - 1(3)까지의 정수 인덱스 스트림을 생성합니다. 이 스트림은 boxed()메서드를 사용하여 Stream<Integer>로 박스화 됩니다.
그런 다음 Comparator.comparingInt(i -> array[i])로 정의된 Comparator를 활용하여 sorted()연산을 사용합니다. 여기서 스트림의 각 index는 i는 배열의 해당 값을 매핑되고 Comparator는 이러한 값을 기반으로 합니다.
마지막으로 collect(collector.toList()) 메서드를 사용하여 정렬된 인덱스를 List<Integer>로 수집합니다.
결론
위의 예제들은 요소의 위치 관계를 유지하는 것이 중요한 다양한 알고리즘과 애플리케이션에서 사용할 수 있을 것입니다.
개인적으로는 깊은 복사로 쓰는 것을 선호하였는데 메모리 측면에서 이부분이 보다 효율적일것 같다는 생각이 들었습니다. 다음에 한번 활용해 비용적 측면을 확인해보는 것도 괜찮을 것 같습니다.
출처: https://www.baeldung.com/java-indices-array-after-sorting
'Development > Java' 카테고리의 다른 글
[JAVA] "Could not create the Java Virtual Machine" 에러 수정 방법 (2) | 2024.09.02 |
---|---|
[Java] 정규식을 사용하여 문자열 바꾸기(back referece와 lookaround 비교) - spring boot gradle (0) | 2024.08.19 |
[JAVA] Iterator.forEachRemaining()과 Iterable.forEach()의 차이점 (0) | 2024.08.12 |
[JAVA] 배열에서 0에 가장 가까운 숫자 찾기 (0) | 2024.08.07 |
[JAVA] CLOB과 String(문자열)간의 변환 (0) | 2024.08.07 |