자바 의 Arrays 라 는 도구 류 를 정말 사용 할 수 있 습 니까?
오늘 자바 의 소스 코드 세 번 째 탄,Arrays 라 는 도구 류 의 소스 코드 를 공유 합 니 다.최근 에 데이터 구 조 를 복습 하면 서 Arrays 안의 정렬 알고리즘 과 이분 검색 등의 실현 을 알 게 되 었 고 수익 이 매우 많 기 때문에 Arrays 와 같은 소스 코드 를 연구 하기 로 결정 했다.부족 한 점 은 논평 구역 에서 교류 하고 지적 하 는 것 을 환영 합 니 다.
1.Arrays 클래스 를 알 고 있 습 니 다.
우선 자바 의 utils 패키지 아래 자바 Collections Framework 의 일원 입 니 다.그것 의 취 지 는 바로 도구 류 로 배열 을 조작 하 는 여러 가지 방법 을 밀봉 했다.예 를 들 어 정렬,2 분 검색,배열 의 복사 등 이다.우리 가 일상적으로 수조 체조 에 대한 기본 적 인 수 요 를 만족 시 키 고 그 밑바닥 의 실현 을 이해 하면 우리 가 그것 을 더욱 잘 사용 할 수 있 을 뿐만 아니 라 더 좋 은 코드 의 사고방식 도 키 울 수 있다.
2.구조 방법
도구 류 이기 때문에 그 구조 방법 은 사유 로 정의 되 고 모든 실현 방법 은 정적 방법 이다.즉,이런 종 류 는 실례 화 되 어 서 는 안 되 고,통속 적 으로 말 하면 new 가 안 된다 는 것 이다.클래스 이름 을 통 해서 만 직접 호출 방법(반사 제외).이렇게 하 는 목적 은 이런 실 용화 할 수 없 는 능력 을 강화 하고 이런 도구 류 로 서 의 근본 적 인 기능 을 강조 하 는 것 이다.원본 코드 는 다음 과 같 습 니 다.
// Suppresses default constructor, ensuring non-instantiability.
private Arrays()
{
}
3.상용 방법의 해석3.1 집합 요 소 를 빠르게 삽입 하 는 방법 asList(T...a):
기본 사용:
/**
*
*/
@Test
public void toArrayTest(){
List<Integer> list = Arrays.asList(2,4,5,6,6);
for (Integer integer : list) {
System.out.print(integer+" ");
}
}
출력 결과:2 4 5 6 6
원본 코드 보기:
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
// ArrayList
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
이 방법의 실현 은 비교적 간단 하 다.바로 Array List 의 구조 방법 을 호출 하 는 것 이 고 매개 변 수 는 하나의 배열 이다.즉,우리 가 구성 하고 자 하 는 수 를 Array List 의 구조 방법 에 전달 하여 예화 하 는 것 이다.3.2 2 점 에서 찾 는 방법
Arrays 클래스 의 2 분 검색 8 가지 기본 유형 은 모두 관련 되 어 있 지만 모두 방법의 과부하 입 니 다.그 실현 원 리 는 모두 같다.여기 서 int 유형 을 예 로 들 어 설명 한다.
기본 사용:
@Test
public void binarySearchTest(){
int[] arrays = {1,4,6,7,9,3};
// 7
int result = Arrays.binarySearch(arrays,7);
System.out.println(result);
}
결과:3
이 방법 은 주로 세 가지 방법 과 관련된다.
//
public static int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}
/*
: a
fromIndex
toIndex
key
*/
public static int binarySearch(int[] a, int fromIndex, int toIndex,
int key) {
//
rangeCheck(a.length, fromIndex, toIndex);
return binarySearch0(a, fromIndex, toIndex, key);
}
// Like public version, but without range checks.
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
//
int mid = (low + high) >>> 1;
int midVal = a[mid];
//
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
물론 실현 의 핵심 방법 은 상술 한 사유 방법binarySearch0()
이라는 방법 이기 때문에 실현 의 논리 도 복잡 하지 않다.첫 번 째 단 계 는 두 변수 가 검색 영역 을 저장 하 는 시작 과 끝 을 설명 하 는 것 입 니 다.
두 번 째 순환,비교,비교 범 위 를 계속 축소 합 니 다.배열 의 값 과 목표 값 이 같 을 때 까지 다음 표 시 를 되 돌려 줍 니 다.찾 지 못 하면 마이너스,즉 아래 의 l 두 줄 코드 를 되 돌려 줍 니 다.
return mid; // key found
return -(low + 1); // key not found.
나 는 이 이분법 이 실현 하 는 하 이 라 이 트 는 바로 중간 값 의 이동 연산 을 구 하 는 것 이 라 고 생각한다.
int mid = (low + high) >>> 1;
어떤 사람 은 왜 이 위 연산 을 사용 해 야 하 는 지,나눗셈 이 안 되 는 지 궁금 해 했다.주로 성능 을 고려 하기 위해 서다.이 위 연산 은 두 기계 주 기 를 차지 하고 곱셈 법 은 네 개의 연산 주 기 를 차지 하기 때문에 이 위 연산 의 속 도 는 곱셈 법의 연산 속도 보다 훨씬 빠 를 것 이다.계 산 량 이 작 으 면 차이 가 크 지 않 을 수 있 지만 계 산 량 이 많 으 면 차이 가 매우 뚜렷 하 다.3.3 배열 의 복사
@Test
public void testCopyArrange(){
//
int [] srcArray = {11,2,244,5,6,54};
// 3
int[] descArray = Arrays.copyOf(srcArray,3);
System.out.println(Arrays.toString(descArray));
}
출력 결과:[11, 2, 244]
소스 코드 분석:
/* :
original
newLength
*/
public static int[] copyOf(int[] original, int newLength) {
// ,
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
분석:주로 로 컬 방법 인 array copy 를 호출 하여 배열 의 지정 한 길 이 를 복사 한 것 입 니 다.소스 코드 가 배열 의 길 이 를 검사 하지 않 은 것 을 볼 수 있 습 니 다.주로arraycopy()
이 방법 을 사용 할 때Math.min()
방법 을 사용 하여 성명 의 길 이 를 안전 한 범위 내 에서 보장 합 니 다.만약 에 복사 한 길이 가 배열 의 길 이 를 초과 하면...모든 배열 을 기본 으로 복사 합 니 다.네 이 티 브 수식 방법 에 대해 서 는 사용 할 수 있 습 니 다여기 봐 봐..
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
물론 배열 이 지정 한 구간 을 복사 해 야 한다 면 ArrayscopyOfRange(int[] original, int from, int to)
의 실현 원리 와arraycopy()
방법의 원 리 를 유사 하 게 사용 할 수 있다.
@Test
public void testCopy(){
int [] srcArray = {11,2,244,5,6,54};
//
int[] descArray = Arrays.copyOfRange(srcArray,0,3);
System.out.println(Arrays.toString(descArray));
}
출력 결과:[11, 2, 244]
주:
copyOfRange(int[] original, int from, int to)
의 매개 변 수 는 복사 결과 에 포함 되 지 않 습 니 다.상기 예 는 색인 이 2 인 요소 만 복사 할 수 있 고 색인 이 3 인 요 소 는 포함 되 지 않 습 니 다.이 점 은 주의해 야 합 니 다.3.4 equals 방법
주로 Object 류 의 equals 방법 을 재 작성 하여 두 배열 의 내용 이 같 는 지,즉 그들 중의 요소 가 같 는 지 비교 하 는 데 사용 합 니 다.
기본 용법:
@Test
public void equalTest(){
int[] array ={1,2,3,4};
int[] result ={1,2,3,4};
System.out.println(Arrays.equals(array,result));
System.out.println(array == result);
}
결과:true
false
소스 코드 를 보기 전에 equals 방법 을 다시 쓴 후에 두 대상 이 비교 하 는 것 은 값,즉 그들의 내용 이라는 점 이 매우 중요 하 다.equals 방법 을 다시 쓰 는 주의사항여기 로 옮 겨..
원본 코드 는 다음 과 같 습 니 다.
public static boolean equals(int[] a, int[] a2) {
//
if (a==a2)
return true;
if (a==null || a2==null)
return false;
int length = a.length;
//
if (a2.length != length)
return false;
//
for (int i=0; i<length; i++)
if (a[i] != a2[i])
return false;
return true;
}
소스 코드 설명 은 다음 과 같 습 니 다.소스 코드 는 네 번 의 판단 을 했 는데 각각 첫 번 째 주소 비교,비어 있 는 지,그리고 길이 의 비교 이 고 마지막 으로 배열 의 각 요 소 를 비교 했다.
다음 의 첫 번 째 판단,즉 첫 번 째 주소 의 비 교 를 설명 할 필요 가 있다.우리 가 배열 변 수 를 설명 할 때 이 변 수 는 배열 의 첫 번 째 주 소 를 대표 합 니 다.아래 코드 를 보 세 요.
@Test
public void equalTest(){
int[] array ={1,2,3,4};
System.out.println(array);
}
결과:[I@4f2410ac // [대표 배열 I 대표 정수@구분자 뒤에 있 는 메모리 주소 16 진수
이것 은 주 소 를 나타 낸다.아니면 하나의 배열 을 설명 할 때 더미 안에 메모리 영역 을 만 들 기 때 문 입 니까?그러나 이 메모리 영역 은 더미 에 비해 작 을 수 있 습 니 다.찾기 가 쉽 지 않 습 니 다.찾기 편 하도록 배열 메모리 의 첫 주 소 를 표시 합 니 다.가상 컴퓨터 는 변수 이름 array 에 주 소 를 전달 합 니 다.이것 도 참조 형식 입 니 다.주소,즉 array 가 메모리 주 소 를 가리 키 는 것 으로 이해 합 니 다.실행 할 때마다 주소 가 다 를 수 있 습 니 다.가상 컴퓨터 가 열 린 메모리 공간 이 다 를 수 있 기 때 문 입 니 다.
이것 을 이해 하면
a==a2
이해 하기 쉽다.만약 두 그룹의 메모리 주소 가 모두 같다 면 두 그룹의 메모리 주 소 는 틀림없이 같다.그리고 프로그램 이 비교적 잘 쓴 곳 은 바로 소스 코드 에서 배열 의 모든 요소 에 대한 비교,즉 아래 의 이 코드 라 고 생각 합 니 다.
for (int i=0; i<length; i++)
if (a[i] != a2[i])
return false;
return true;
판단 조건 으로 사용a[i] != a2[i]
하면 비교 횟수 를 줄 이 고 성능 을 높 일 수 있다.만약 에 여기 가 똑 같은 비교 라면 매번 전체 배열 을 옮 겨 다 녀 야 한다.만약 에 데이터 의 양 이 많 으 면 성능 이 많이 느 릴 것 이다.또 한 번 소스 의 매력 에 감탄 했다.3.5 정렬 방법 sort()와 parallelsert()
Arrays
이 유형 은 주로 두 가지 유형의 정렬 방법 직렬sort()
과 병렬parallelSort()
두 가지 방법 과 관련 되 는데 물론 대상 의 정렬 과 기본 유형의 정렬 도 다르다.여 기 는 int[]유형의 예 입 니 다.설명 을 하 다.먼저 두 가지 방법의 성능 을 비교한다.
public final int UPPER_LIMIT = 0xffffff;
final int ROUNDS = 10;
final int INCREMENT = 5;
final int INIT_SIZE = 1000;
@Test
public void sortAndParallelSortTest(){
//
for (int capacity = INIT_SIZE; capacity < UPPER_LIMIT ; capacity*= INCREMENT) {
ArrayList<Integer> list = new ArrayList<>(capacity);
for (int j = 0; j < capacity; j++) {
list.add((int) (Math.random()*capacity));
}
double avgTimeOfParallelSort = 0;
double avgTimeOfSort = 0;
for (int j = 0; j <= ROUNDS ; j++) {
//
Collections.shuffle(list);
Integer[] arr1 = list.toArray(new Integer[capacity]);
Integer[] arr2 = arr1.clone();
avgTimeOfParallelSort += counter(arr1,true);
avgTimeOfSort += counter(arr2, false);
}
//
output(capacity,avgTimeOfParallelSort/ROUNDS,avgTimeOfSort/ROUNDS);
}
}
private void output(int capacity, double v, double v1) {
System.out.println("======================= =========");
System.out.println("Capacity"+capacity);
System.out.println("ParallelSort"+v);
System.out.println("Sort"+v1);
System.out.println(" :"+(v < v1 ? "ParallelSort":"Sort"));
}
//
private double counter(Integer[] arr1, boolean b) {
long begin,end;
begin = System.nanoTime();
if(b){
Arrays.parallelSort(arr1);
}else{
Arrays.parallelSort(arr1);
}
end = System.nanoTime();
return BigDecimal.valueOf(end-begin,9).doubleValue();
}
부분의 테스트 결과:===========================테스트 정렬 의 시간================
Capacity1000
ParallelSort6.284099999999999E-4
Sort5.599599999999999E-4
비교적 빠 른 정렬 은:Sort
===========================테스트 정렬 의 시간================
Capacity5000
ParallelSort0.00163599
Sort0.0018313699999999995
빠 른 정렬 은:ParallelSort
데이터 양 이 비교적 적은 상황 에서 sort()방법 을 사용 하 는 것 이 빠 르 고 한 한도 값 이 지나 면 ParallelSort()라 는 방법 이 성능 이 좋 은 것 을 볼 수 있 습 니 다.이 한도 값 은 얼마 일 까요?
먼저 parallelsert 의 소스 코드 를 살 펴 보 겠 습 니 다.
public static void parallelSort(int[] a) {
int n = a.length, p, g;
if (n <= MIN_ARRAY_SORT_GRAN ||
(p = ForkJoinPool.getCommonPoolParallelism()) == 1)
DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
else
new ArraysParallelSortHelpers.FJInt.Sorter
(null, a, new int[n], 0, n, 0,
((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
MIN_ARRAY_SORT_GRAN : g).invoke();
}
배열 의 길이 가MIN_ARRAY_SORT_GRAN
보다 작 거나p = ForkJoinPool.getCommonPoolParallelism()) == 1
(단일 스 레 드 에서)일 때 sort()정렬 의 바 텀 을 호출 하여 이 루어 진DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
Arrays 의 시작 정 의 는 다음 과 같 습 니 다.
private static final int MIN_ARRAY_SORT_GRAN = 1 << 13; // 8192
두 가 지 를 비교 하면 배열 의 길이 가 비교적 크 거나 다 중 스 레 드 의 경우 병렬 정렬 을 우선 고려 하고 그렇지 않 으 면 직렬 정렬 을 사용 하 는 것 이다.두 정렬 의 핵심 사상:
3.6 toString 방법
기본 용법:
@Test
public void toStringTest(){
int[] array = {1,3,2,5};
System.out.println(Arrays.toString(array));
}
결과:[1, 3, 2, 5]
소스 코드 분석 은 다음 과 같다.
public static String toString(int[] a) {
// 1.
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
// 2. StringBuilder
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
구체 적 인 실현 은 이미 소스 코드 의 주석 에서 설명 되 었 다.이 방법 은 기본 데이터 형식 에 있어 서 배열 을 편리 하 게 옮 겨 다 닌 다.근본 을 캐 고 근원 을 거 슬러 야만 활보 하여 앞으로 나 아 갈 수 있다.
참고 자료
https://www.jb51.net/article/180770.htm
https://www.jb51.net/article/116323.htm
javaSE 의 공식 문서.
자바 에 있 는 Arrays 라 는 도구 류 를 사용 할 수 있 습 니까?
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.