Szukaj…


Wprowadzenie

Tablice pozwalają na przechowywanie i wyszukiwanie dowolnej ilości wartości. Są one analogiczne do wektorów w matematyce. Tablice tablic są analogiczne do macierzy i działają jak tablice wielowymiarowe. Tablice mogą przechowywać dowolne dane dowolnego typu: prymitywy takie jak int lub typy referencyjne takie jak Object .

Składnia

  • ArrayType[] myArray; // Deklarowanie tablic
  • ArrayType myArray[]; // Kolejna poprawna składnia (rzadziej używana i odradzana)
  • ArrayType[][][] myArray; // Deklarowanie wielowymiarowych poszarpanych tablic (powtórz [] s)
  • ArrayType myVar = myArray[index]; // Dostęp do (odczyt) elementu w indeksie
  • myArray[index] = value; // Przypisz wartość do index pozycji tablicy
  • ArrayType[] myArray = new ArrayType[arrayLength]; // Składnia inicjalizacji tablicy
  • int[] ints = {1, 2, 3}; // Składnia inicjalizacji tablicy z podanymi wartościami, długość jest wywnioskowana z liczby podanych wartości: {[wartość1 [, wartość2] *]}
  • new int[]{4, -5, 6} // Can be used as argument, without a local variable
  • int[] ints = new int[3]; // same as {0, 0, 0}
  • int[][] ints = {{1, 2}, {3}, null}; // Inicjalizacja macierzy wielowymiarowych. int [] rozszerza Object (podobnie jak anyType []), więc null jest prawidłową wartością.

Parametry

Parametr Detale
ArrayType Rodzaj tablicy. Może to być prymitywny ( int , long , byte ) lub Objects ( String , MyObject itp.).
indeks Indeks odnosi się do pozycji określonego obiektu w tablicy.
długość Każda tablica podczas tworzenia potrzebuje określonej długości. Odbywa się to albo podczas tworzenia pustej tablicy ( new int[3] ), albo domyślnie przy określaniu wartości ( {1, 2, 3} ).

Tworzenie i inicjowanie tablic

Podstawowe przypadki

int[]   numbers1 = new int[3];                 // Array for 3 int values, default value is 0
int[]   numbers2 = { 1, 2, 3 };                // Array literal of 3 int values
int[]   numbers3 = new int[] { 1, 2, 3 };      // Array of 3 int values initialized
int[][] numbers4 = { { 1, 2 }, { 3, 4, 5 } };  // Jagged array literal
int[][] numbers5 = new int[5][];               // Jagged array, one dimension 5 long
int[][] numbers6 = new int[5][4];              // Multidimensional array: 5x4

Tablice można tworzyć przy użyciu dowolnego typu pierwotnego lub referencyjnego.

float[]  boats = new float[5];          // Array of five 32-bit floating point numbers.
double[] header = new double[] { 4.56, 332.267, 7.0, 0.3367, 10.0 };
                                       // Array of five 64-bit floating point numbers.
String[] theory = new String[] { "a", "b", "c" };
                                       // Array of three strings (reference type).
Object[] dArt = new Object[] { new Object(), "We love Stack Overflow.", new Integer(3) };
                                       // Array of three Objects (reference type).

W ostatnim przykładzie zauważ, że podtypy zadeklarowanego typu tablicy są dozwolone w tablicy.

Tablice dla typów zdefiniowanych przez użytkownika można również budować podobnie do typów pierwotnych

UserDefinedClass[] udType = new UserDefinedClass[5];

Tablice, kolekcje i strumienie

Java SE 1.2
// Parameters require objects, not primitives

// Auto-boxing happening for int 127 here
Integer[]       initial        = { 127, Integer.valueOf( 42 ) };
List<Integer>   toList         = Arrays.asList( initial );  // Fixed size! 

// Note: Works with all collections
Integer[]       fromCollection = toList.toArray( new Integer[toList.size()] );

//Java doesn't allow you to create an array of a parameterized type
List<String>[]  list = new ArrayList<String>[2];  // Compilation error!
Java SE 8
// Streams - JDK 8+
Stream<Integer> toStream       = Arrays.stream( initial );
Integer[]       fromStream     = toStream.toArray( Integer[]::new );

Wprowadzenie

Tablica jest strukturą danych, która przechowuje stałą liczbę prymitywnych wartości lub odniesień do instancji obiektów.

Każdy element w tablicy jest nazywany elementem, a do każdego elementu można uzyskać dostęp za pomocą indeksu liczbowego. Długość tablicy jest ustalana podczas tworzenia tablicy:

int size = 42;
int[] array = new int[size];

Rozmiar tablicy jest ustalany w czasie wykonywania po zainicjowaniu. Nie można go zmienić po inicjalizacji. Jeśli rozmiar musi być zmienny w czasie wykonywania, zamiast tego należy użyć klasy Collection takiej jak ArrayList . ArrayList przechowuje elementy w tablicy i obsługuje zmianę rozmiaru poprzez przydzielenie nowej tablicy i kopiowanie elementów ze starej tablicy.

Jeśli tablica jest typu pierwotnego, tj

int[] array1 = { 1,2,3 };
int[] array2 = new int[10];

wartości są przechowywane w samej tablicy. W przypadku braku inicjatora (jak w array2 powyżej) domyślną wartością przypisaną do każdego elementu jest 0 (zero).

Jeśli typ tablicy jest odwołaniem do obiektu, jak w

SomeClassOrInterface[] array = new SomeClassOrInterface[10];

następnie tablica zawiera odwołania do obiektów typu SomeClassOrInterface . Odwołania te mogą odnosić się do wystąpienia SomeClassOrInterface lub dowolnej podklasy (dla klas) lub klasy implementującej (dla interfejsów) SomeClassOrInterface . Jeśli deklaracja tablicowa nie ma inicjatora, wówczas do każdego elementu przypisywana jest domyślna wartość null .

Ponieważ wszystkie tablice są indeksowane int , rozmiar tablicy musi być określony przez int . Rozmiar tablicy nie może być określony jako long :

long size = 23L;
int[] array = new int[size]; // Compile-time error:
                             // incompatible types: possible lossy conversion from
                             // long to int

Tablice używają zerowego systemu indeksowania , co oznacza, że indeksowanie zaczyna się od 0 a kończy na length - 1 .

Na przykład poniższy obraz przedstawia tablicę o rozmiarze 10 . Tutaj pierwszy element ma indeks 0 a ostatni element ma indeks 9 , zamiast pierwszego elementu o indeksie 1 a ostatni element o indeksie 10 (patrz rysunek poniżej).

Tablica 10 elementów

Dostęp do elementów tablic odbywa się w stałym czasie . Oznacza to, że dostęp do pierwszego elementu tablicy ma taki sam koszt (w czasie) dostępu do drugiego elementu, trzeciego elementu i tak dalej.

Java oferuje kilka sposobów definiowania i inicjowania tablic, w tym notacji dosłownych i konstruktorów . Podczas deklarowania tablic za pomocą new Type[length] każdy element zostanie zainicjowany przy użyciu następujących wartości domyślnych:

Tworzenie i inicjowanie tablic typu pierwotnego

int[] array1 = new int[] { 1, 2, 3 }; // Create an array with new operator and 
                                      // array initializer.
int[] array2 = { 1, 2, 3 };           // Shortcut syntax with array initializer.
int[] array3 = new int[3];            // Equivalent to { 0, 0, 0 }
int[] array4 = null;                  // The array itself is an object, so it
                                      // can be set as null.

Podczas deklarowania tablicy, [] pojawi się jako część typu na początku deklaracji (po nazwie typu) lub jako część deklaratora dla określonej zmiennej (po nazwie zmiennej), lub oba:

int array5[];       /* equivalent to */  int[] array5;
int a, b[], c[][];  /* equivalent to */  int a; int[] b; int[][] c;
int[] a, b[];       /* equivalent to */  int[] a; int[][] b;
int a, []b, c[][];  /* Compilation Error, because [] is not part of the type at beginning
                       of the declaration, rather it is before 'b'. */    
// The same rules apply when declaring a method that returns an array:
int foo()[] { ... } /* equivalent to */  int[] foo() { ... }

W poniższym przykładzie obie deklaracje są poprawne i można je skompilować i uruchomić bez żadnych problemów. Jednak zarówno Konwencja kodowania Java , jak i Przewodnik po stylu Java firmy Google zniechęcają formularz za pomocą nawiasów po nazwie zmiennej - nawiasy identyfikują typ tablicy i powinny być wyświetlane z oznaczeniem typu . To samo należy zastosować w przypadku sygnatur zwracających metody.

float array[]; /* and */ int foo()[] { ... } /* are discouraged */
float[] array; /* and */ int[] foo() { ... } /* are encouraged */

Odradzany typ ma na celu pomieścić przechodzących użytkowników C , którzy znają składnię C, która zawiera nawiasy po nazwie zmiennej.

W Javie można mieć tablice o rozmiarze 0 :

int[] array = new int[0]; // Compiles and runs fine.
int[] array2 = {};        // Equivalent syntax.

Ponieważ jednak jest to pusta tablica, nie można z niej odczytać ani przypisać żadnych elementów:

array[0] = 1;     // Throws java.lang.ArrayIndexOutOfBoundsException.
int i = array2[0]; // Also throws ArrayIndexOutOfBoundsException.

Takie puste tablice są zwykle przydatne jako wartości zwracane, więc kod wywołujący musi martwić się tylko NullPointerException tablicy, a nie potencjalną wartością null która może prowadzić do NullPointerException .

Długość tablicy musi być nieujemną liczbą całkowitą:

int[] array = new int[-1]; // Throws java.lang.NegativeArraySizeException

Rozmiar tablicy można określić za pomocą publicznego pola końcowego o nazwie length :

System.out.println(array.length); // Prints 0 in this case.

Uwaga : array.length zwraca rzeczywisty rozmiar tablicy, a nie liczbę elementów tablicy, którym przypisano wartość, w przeciwieństwie do ArrayList.size() która zwraca liczbę elementów tablicy, którym przypisano wartość.

Tworzenie i inicjowanie tablic wielowymiarowych

Najprostszym sposobem utworzenia tablicy wielowymiarowej jest:

int[][] a = new int[2][3];

Stworzy dwa trzy-macierzowe tablice int a[0] i a[1] . Jest to bardzo podobne do klasycznej inicjalizacji w kształcie litery C prostokątnych tablic wielowymiarowych.

Możesz tworzyć i inicjalizować w tym samym czasie:

int[][] a = { {1, 2}, {3, 4}, {5, 6} };

W przeciwieństwie do C , gdzie obsługiwane są tylko prostokątne tablice wielowymiarowe, tablice wewnętrzne nie muszą być tej samej długości, a nawet zdefiniowane:

int[][] a = { {1}, {2, 3}, null };

Tutaj a[0] jest tablicą int o jednej długości, podczas a[1] jest tablicą int o dwóch długościach, a a[2] ma null . Takie tablice nazywane są tablicami poszarpanymi lub tablicami poszarpanymi , to znaczy tablicami tablic. Wielowymiarowe tablice w Javie są implementowane jako tablice tablic, tzn. array[i][j][k] jest równoważna ((array[i])[j])[k] . W przeciwieństwie do C # , array[i,j] składniowa array[i,j] nie jest obsługiwana w Javie.

Wielowymiarowa reprezentacja tablic w Javie

Wizualna reprezentacja wielowymiarowej tablicy Java

Źródło - Live w Ideone

Tworzenie i inicjowanie tablic typów referencyjnych

String[] array6 = new String[] { "Laurel", "Hardy" }; // Create an array with new 
                                                      // operator and array initializer.
String[] array7 = { "Laurel", "Hardy" };              // Shortcut syntax with array 
                                                      // initializer.
String[] array8 = new String[3];                      // { null, null, null }
String[] array9 = null;                               // null

Żyj na Ideone

Oprócz literałów i prymitywów String przedstawionych powyżej, składnia skrótu do inicjalizacji tablicy działa również z kanonicznymi typami Object :

Object[] array10 = { new Object(), new Object() };

Ponieważ tablice są kowariantne, tablicę typu referencyjnego można zainicjować jako tablicę podklasy, chociaż ArrayStoreException zostanie ArrayStoreException , jeśli spróbujesz ustawić element na coś innego niż String :

Object[] array11 = new String[] { "foo", "bar", "baz" };
array11[1] = "qux"; // fine
array11[1] = new StringBuilder(); // throws ArrayStoreException

Nie można do tego użyć składni skrótu, ponieważ składnia skrótu miałaby niejawny typ Object[] .

Tablicę można zainicjować z zerowymi elementami za pomocą parametru String[] emptyArray = new String[0] . Na przykład tablica o takiej zerowej długości jest używana do tworzenia Array z Collection gdy metoda potrzebuje typu środowiska wykonawczego obiektu.

Zarówno w typach pierwotnych, jak i referencyjnych, inicjalizacja pustej tablicy (na przykład String[] array8 = new String[3] ) zainicjuje tablicę z wartością domyślną dla każdego typu danych .

Tworzenie i inicjowanie tablic typów ogólnych

W klasach ogólnych tablic typów ogólnych nie można zainicjować w ten sposób z powodu kasowania typu :

public class MyGenericClass<T> {
    private T[] a;

    public MyGenericClass() {
        a = new T[5]; // Compile time error: generic array creation
    }
}

Zamiast tego można je utworzyć przy użyciu jednej z następujących metod: (zwróć uwagę, że wygenerują one niesprawdzone ostrzeżenia)

  1. Tworząc tablicę Object i rzutując ją na typ ogólny:

    a = (T[]) new Object[5];
    

    Jest to najprostsza metoda, ale ponieważ podstawowa tablica jest nadal typu Object[] , ta metoda nie zapewnia bezpieczeństwa typu. Dlatego ta metoda tworzenia tablicy najlepiej jest stosować tylko w klasie ogólnej - niejawnej.

  2. Korzystając z Array.newInstance z parametrem klasy:

    public MyGenericClass(Class<T> clazz) {
        a = (T[]) Array.newInstance(clazz, 5);
    }
    

    Tutaj klasa T musi być jawnie przekazana do konstruktora. Typem Array.newInstance jest zawsze Object . Jednak ta metoda jest bezpieczniejsza, ponieważ nowo utworzona tablica jest zawsze typu T[] , a zatem może być bezpiecznie eksternalizowana.

Wypełnianie tablicy po inicjalizacji

Java SE 1.2

Arrays.fill() może być użyty do wypełnienia tablicy tą samą wartością po inicjalizacji:

Arrays.fill(array8, "abc");        // { "abc", "abc", "abc" }

Żyj na Ideone

fill() może również przypisać wartość do każdego elementu określonego zakresu tablicy:

Arrays.fill(array8, 1, 2, "aaa");  // Placing "aaa" from index 1 to 2.

Żyj na Ideone

Java SE 8

Od wersji Java 8 metoda setAll i jej Concurrent odpowiednik parallelSetAll mogą być używane do ustawiania każdego elementu tablicy na generowane wartości. Metodom tym przekazywana jest funkcja generatora, która akceptuje indeks i zwraca żądaną wartość dla tej pozycji.

Poniższy przykład tworzy tablicę liczb całkowitych i ustawia wszystkie jej elementy na odpowiadające im wartości indeksu:

int[] array = new int[5];
Arrays.setAll(array, i -> i); // The array becomes { 0, 1, 2, 3, 4 }.

Żyj na Ideone

Oddzielna deklaracja i inicjalizacja tablic

Wartość indeksu dla elementu tablicy musi być liczbą całkowitą (0, 1, 2, 3, 4, ...) i mniejszą niż długość tablicy (indeksy są zerowe). W przeciwnym razie zostanie zgłoszony wyjątek ArrayIndexOutOfBoundsException :

int[] array9;             // Array declaration - uninitialized
array9 = new int[3];      // Initialize array  - { 0, 0, 0 }
array9[0] = 10;           // Set index 0 value - { 10, 0, 0 }
array9[1] = 20;           // Set index 1 value - { 10, 20, 0 }
array9[2] = 30;           // Set index 2 value - { 10, 20, 30 }

Tablic nie można ponownie inicjować za pomocą składni skrótu inicjalizującego tablicę

Ponowna inicjalizacja tablicy za pomocą składni skrótu za pomocą inicjatora tablicy nie jest możliwa, ponieważ inicjator tablicy można podać tylko w deklaracji pola lub deklaracji zmiennej lokalnej lub jako część wyrażenia tworzenia tablicy.

Możliwe jest jednak utworzenie nowej tablicy i przypisanie jej do zmiennej używanej do odwoływania się do starej tablicy. Chociaż powoduje to, że tablica, do której odwołuje się ta zmienna, jest ponownie inicjowana, zawartość zmiennej jest zupełnie nową tablicą. W tym celu można użyć new operatora z inicjatorem tablicy i przypisać do zmiennej tablicowej:

// First initialization of array
int[] array = new int[] { 1, 2, 3 };

// Prints "1 2 3 ".
for (int i : array) {
    System.out.print(i + " ");
}

// Re-initializes array to a new int[] array.
array = new int[] { 4, 5, 6 };

// Prints "4 5 6 ".
for (int i : array) {
    System.out.print(i + " ");
}

array = { 1, 2, 3, 4 }; // Compile-time error! Can't re-initialize an array via shortcut 
                        // syntax with array initializer.

Żyj na Ideone

Tworzenie tablicy z kolekcji

Dwie metody w java.util.Collection tworzą tablicę z kolekcji:

Object[] toArray() może być używany w następujący sposób:

Java SE 5
Set<String> set = new HashSet<String>();
set.add("red");
set.add("blue");

// although set is a Set<String>, toArray() returns an Object[] not a String[]
Object[] objectArray = set.toArray();

<T> T[] toArray(T[] a) można korzystać w następujący sposób:

Java SE 5
Set<String> set = new HashSet<String>();
set.add("red");
set.add("blue");

// The array does not need to be created up front with the correct size.
// Only the array type matters. (If the size is wrong, a new array will
// be created with the same type.)
String[] stringArray = set.toArray(new String[0]);  

// If you supply an array of the same size as collection or bigger, it
// will be populated with collection values and returned (new array
// won't be allocated)
String[] stringArray2 = set.toArray(new String[set.size()]);

Różnica między nimi polega na czymś więcej niż tylko na wynikach bez typowania i na typach. Ich wydajność może się również różnić (szczegółowe informacje można znaleźć w tej sekcji analizy wydajności ):

  • Object[] toArray() używa wektoryzowanej arraycopy , która jest znacznie szybsza niż arraycopy sprawdzeniem arraycopy zastosowana w T[] toArray(T[] a) .
  • T[] toArray(new T[non-zero-size]) musi wyzerować tablicę w czasie wykonywania, podczas gdy T[] toArray(new T[0]) nie. Takie unikanie sprawia, że drugie połączenie jest szybsze niż pierwsze. Szczegółowa analiza tutaj: Tablice Mądrości Starożytnych .
Java SE 8

Począwszy od wersji Java SE 8+, w której wprowadzono koncepcję Stream , możliwe jest użycie Stream utworzonego przez kolekcję w celu utworzenia nowego Array przy użyciu metody Stream.toArray .

String[] strings = list.stream().toArray(String[]::new);

Przykłady zaczerpnięte z dwóch odpowiedzi ( 1 , 2 ) na Konwertowanie „ArrayList na” String [] ”w Javie na przepełnieniu stosu.

Tablice do łańcucha

Java SE 5

Od wersji Java 1.5 można uzyskać String reprezentujący zawartość określonej tablicy bez iteracji po każdym elemencie. Wystarczy użyć Arrays.toString(Object[]) lub Arrays.deepToString(Object[]) dla tablic wielowymiarowych:

int[] arr = {1, 2, 3, 4, 5};
System.out.println(Arrays.toString(arr));      // [1, 2, 3, 4, 5]

int[][] arr = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};
System.out.println(Arrays.deepToString(arr));  // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Arrays.toString() metoda wykorzystuje Object.toString() Sposób wytwarzania String wartości każdej pozycji w tablicy, obok pierwotnego macierzowych, może on być stosowany do wszystkich rodzajów tablic. Na przykład:

public class Cat { /* implicitly extends Object */
    @Override
    public String toString() {
      return "CAT!";
    }
}

Cat[] arr = { new Cat(), new Cat() };
System.out.println(Arrays.toString(arr));        // [CAT!, CAT!]

Jeśli nie przesłonięte toString() istnieje dla klasy następnie odziedziczone toString() od Object będzie używany. Zazwyczaj dane wyjściowe nie są wtedy bardzo przydatne, na przykład:

public class Dog {
    /* implicitly extends Object */
}

Dog[] arr = { new Dog() };
System.out.println(Arrays.toString(arr));        // [Dog@17ed40e0]

Tworzenie listy z tablicy

Arrays.asList() Sposób ten może być używany do zwrócenia stałym rozmiarze List zawierającej elementy w danym układzie. Wynikowa List będzie tego samego typu parametru, co podstawowy typ tablicy.

String[] stringArray = {"foo", "bar", "baz"};
List<String> stringList = Arrays.asList(stringArray);

Uwaga : Ta lista jest wspierana przez ( widok ) oryginalnej tablicy, co oznacza, że wszelkie zmiany na liście zmienią tablicę i odwrotnie. Jednak zmiany na liście, które zmieniłyby jej rozmiar (a tym samym długość tablicy), zgłoszą wyjątek.

Aby utworzyć kopię listy, użyj konstruktora java.util.ArrayList przyjmując jako argument Collection :

Java SE 5
String[] stringArray = {"foo", "bar", "baz"};
List<String> stringList = new ArrayList<String>(Arrays.asList(stringArray));
Java SE 7

W Javie SE 7 i nowszych można użyć pary nawiasów kątowych <> (pusty zestaw argumentów typu), który nazywa się Diamentem . Kompilator może określić argumenty typu na podstawie kontekstu. Oznacza to, że informacje o typie można pominąć podczas wywoływania konstruktora ArrayList i będą one automatycznie wywnioskowane podczas kompilacji. Nazywa się to Wnioskowaniem Typu, które jest częścią Java Generics .

// Using Arrays.asList()

String[] stringArray = {"foo", "bar", "baz"};
List<String> stringList = new ArrayList<>(Arrays.asList(stringArray));

// Using ArrayList.addAll()

String[] stringArray = {"foo", "bar", "baz"};
ArrayList<String> list = new ArrayList<>();
list.addAll(Arrays.asList(stringArray));

// Using Collections.addAll()

String[] stringArray = {"foo", "bar", "baz"};
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, stringArray);

Warto zwrócić uwagę na Diament, że nie można go używać z Klasami Anonimowymi .

Java SE 8
// Using Streams

int[] ints = {1, 2, 3};
List<Integer> list = Arrays.stream(ints).boxed().collect(Collectors.toList());

String[] stringArray = {"foo", "bar", "baz"};
List<Object> list = Arrays.stream(stringArray).collect(Collectors.toList());

Ważne uwagi dotyczące korzystania z metody Arrays.asList ()

  • Ta metoda zwraca List , który jest instancją Arrays$ArrayList (statyczna wewnętrzna klasa Arrays ), a nie java.util.ArrayList . Wynikowa List ma stały rozmiar. Oznacza to, że dodawanie lub usuwanie elementów nie jest obsługiwane i spowoduje zgłoszenie UnsupportedOperationException :

    stringList.add("something"); // throws java.lang.UnsupportedOperationException
    
  • Nowa List mogą być tworzone przez przekazywanie tablicy oparciem List do konstruktora nowej List . Spowoduje to utworzenie nowej kopii danych, która ma zmienny rozmiar i nie jest poparta oryginalną tablicą:

    List<String> modifiableList = new ArrayList<>(Arrays.asList("foo", "bar"));
    
  • Wywołanie <T> List<T> asList(T... a) na pierwotnej tablicy, takiej jak int[] , spowoduje utworzenie List<int[]> której jedynym elementem jest pierwotna tablica pierwotna zamiast rzeczywistych elementów tablicy źródłowej.

    Przyczyną takiego zachowania jest to, że typów pierwotnych nie można używać zamiast parametrów typu ogólnego, dlatego cała tablica pierwotna zastępuje w tym przypadku parametr typu ogólnego. Aby przekonwertować prymitywną tablicę na List , przede wszystkim przekonwertuj prymitywną tablicę na tablicę odpowiedniego typu opakowania (tj. Arrays.asList na Arrays.asList Integer[] zamiast int[] ).

    Dlatego wypisze to false :

    int[] arr = {1, 2, 3};      // primitive array of int
    System.out.println(Arrays.asList(arr).contains(1));
    

    Zobacz demo

    Z drugiej strony, wypisze to true :

    Integer[] arr = {1, 2, 3};  // object array of Integer (wrapper for int)
    System.out.println(Arrays.asList(arr).contains(1));
    

    Zobacz demo

    Spowoduje to również wydrukowanie wartości true , ponieważ tablica będzie interpretowana jako liczba Integer[] ):

    System.out.println(Arrays.asList(1,2,3).contains(1));
    

    Zobacz demo

Wielowymiarowe i postrzępione tablice

Możliwe jest zdefiniowanie tablicy o więcej niż jednym wymiarze. Zamiast być dostępnym poprzez podanie jednego indeksu, dostęp do tablicy wielowymiarowej uzyskuje się poprzez określenie indeksu dla każdego wymiaru.

Deklaracja tablicy wielowymiarowej może być wykonana przez dodanie [] dla każdego wymiaru do regularnej dekleracji tablicy. Na przykład, aby utworzyć dwuwymiarową tablicę int , dodaj kolejny zestaw nawiasów do deklaracji, na przykład int[][] . Dzieje się tak w przypadku tablic trójwymiarowych ( int[][][] ) i tak dalej.


Aby zdefiniować tablicę dwuwymiarową z trzema rzędami i trzema kolumnami:

int rows = 3;
int columns = 3;
int[][] table = new int[rows][columns];

Tablica może być indeksowana i przypisywać do niej wartości za pomocą tej konstrukcji. Zauważ, że nieprzypisane wartości są wartościami domyślnymi dla typu tablicy, w tym przypadku 0 dla int .

table[0][0] = 0;
table[0][1] = 1;
table[0][2] = 2;

Możliwe jest także tworzenie wymiarów jednocześnie, a nawet tworzenie tablic nieprostokątnych. Są one częściej określane jako tablice poszarpane .

int[][] nonRect = new int[4][];

Należy zauważyć, że chociaż możliwe jest zdefiniowanie dowolnego wymiaru poszarpanej tablicy, należy zdefiniować jej poprzedni poziom.

// valid
String[][] employeeGraph = new String[30][];

// invalid
int[][] unshapenMatrix = new int[][10];

// also invalid
int[][][] misshapenGrid = new int[100][][10];

Jak tablice wielowymiarowe są reprezentowane w Javie

Reprezentacja tablicy wielowymiarowej w java

Źródło obrazu: http://math.hws.edu/eck/cs124/javanotes3/c8/s5.html


Dosłowna intializacja tablic

Tablice wielowymiarowe i tablice postrzępione mogą być również inicjalizowane dosłownie. Następujące deklaruje i wypełnia tablicę int 2x3:

int[][] table = {
    {1, 2, 3},
    {4, 5, 6}
};

Uwaga : poszarpane podgrupy mogą być również null . Na przykład poniższy kod deklaruje i wypełnia dwuwymiarową tablicę int której pierwsza podtablica jest null , druga podtablica ma zerową długość, trzecia podtablica ma jedną długość, a ostatnia podtablica jest tablicą o dwóch długościach:

int[][] table = {
    null,
    {},
    {1},
    {1,2}
};

W przypadku tablic wielowymiarowych można wyodrębnić tablice wymiarów niższego poziomu za pomocą ich indeksów:

int[][][] arr = new int[3][3][3];
int[][] arr1 = arr[0]; // get first 3x3-dimensional array from arr
int[] arr2 = arr1[0]; // get first 3-dimensional array from arr1
int[] arr3 = arr[0]; // error: cannot convert from int[][] to int[]

ArrayIndexOutOfBoundsException

ArrayIndexOutOfBoundsException jest ArrayIndexOutOfBoundsException gdy uzyskiwany jest dostęp do nieistniejącego indeksu tablicy.

Tablice są indeksowane od zera, więc indeks pierwszego elementu wynosi 0 a indeksem ostatniego elementu jest pojemność tablicy minus 1 (tzn. array.length - 1 ).

Dlatego każde żądanie elementu tablicy według indeksu i musi spełniać warunek 0 <= i < array.length , w przeciwnym razie 0 <= i < array.length ArrayIndexOutOfBoundsException .


Poniższy kod jest prostym przykładem, w którym ArrayIndexOutOfBoundsException jest ArrayIndexOutOfBoundsException .

String[] people = new String[] { "Carol", "Andy" };

// An array will be created:
// people[0]: "Carol"
// people[1]: "Andy"

// Notice: no item on index 2. Trying to access it triggers the exception:
System.out.println(people[2]);  // throws an ArrayIndexOutOfBoundsException.

Wynik:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
    at your.package.path.method(YourClass.java:15)

Zauważ, że dostęp do nielegalnego indeksu jest również uwzględniony w wyjątku ( 2 w przykładzie); informacje te mogą być przydatne do znalezienia przyczyny wyjątku.


Aby tego uniknąć, po prostu sprawdź, czy indeks mieści się w granicach tablicy:

int index = 2;
if (index >= 0 && index < people.length) {
    System.out.println(people[index]);
} 

Uzyskiwanie długości tablicy

Tablice to obiekty, które zapewniają przestrzeń do przechowywania do wielkości elementów określonego typu. Rozmiar tablicy nie może być modyfikowany po jej utworzeniu.

int[] arr1 = new int[0];
int[] arr2 = new int[2];
int[] arr3 = new int[]{1, 2, 3, 4};
int[] arr4 = {1, 2, 3, 4, 5, 6, 7};

int len1 = arr1.length; // 0
int len2 = arr2.length; // 2
int len3 = arr3.length; // 4
int len4 = arr4.length; // 7

Pole length w tablicy przechowuje rozmiar tablicy. Jest to final pole i nie można go modyfikować.

Ten kod pokazuje różnicę między length tablicy a ilością obiektów przechowywanych w tablicy.

public static void main(String[] args) {
    Integer arr[] = new Integer[] {1,2,3,null,5,null,7,null,null,null,11,null,13};

    int arrayLength = arr.length;
    int nonEmptyElementsCount = 0;

    for (int i=0; i<arrayLength; i++) {
        Integer arrElt = arr[i];
        if (arrElt != null) {
            nonEmptyElementsCount++;
        }
    }

    System.out.println("Array 'arr' has a length of "+arrayLength+"\n"
                            + "and it contains "+nonEmptyElementsCount+" non-empty values");
}

Wynik:

Array 'arr' has a length of 13
and it contains 7 non-empty values

Porównywanie tablic dla równości

Typy tablic dziedziczą swoje implementacje equals() (i hashCode() ) z java.lang.Object , więc equals() zwróci true tylko podczas porównywania z dokładnie tym samym obiektem tablicy. Aby porównać tablice pod kątem równości w oparciu o ich wartości, użyj java.util.Arrays.equals , który jest przeciążony dla wszystkich typów tablic.

int[] a = new int[]{1, 2, 3};
int[] b = new int[]{1, 2, 3};
System.out.println(a.equals(b)); //prints "false" because a and b refer to different objects
System.out.println(Arrays.equals(a, b)); //prints "true" because the elements of a and b have the same values

Gdy typ elementu jest typem referencyjnym, Arrays.equals() wywołuje equals() na elementach tablicy w celu ustalenia równości. W szczególności, jeśli typ elementu sam jest typem tablicowym, zostanie użyte porównanie tożsamości. Aby porównać tablice wielowymiarowe pod kątem równości, użyj Arrays.deepEquals() zamiast tego:

int a[] = { 1, 2, 3 };
int b[] = { 1, 2, 3 };

Object[] aObject = { a }; // aObject contains one element
Object[] bObject = { b }; // bObject contains one element

System.out.println(Arrays.equals(aObject, bObject)); // false
System.out.println(Arrays.deepEquals(aObject, bObject));// true

Ponieważ zestawy i mapy używają funkcji equals() i hashCode() , tablice na ogół nie są przydatne jako elementy zestawu lub klucze mapy. Zawiń je w klasę pomocniczą, która implementuje equals() i hashCode() pod względem elementów tablicy, lub przekonwertuj je na instancje List i przechowuj listy.

Tablice do przesyłania strumieniowego

Java SE 8

Konwertowanie tablicy obiektów na Stream :

String[] arr = new String[] {"str1", "str2", "str3"};
Stream<String> stream = Arrays.stream(arr);

Konwersja tablicy prymitywów na Stream za pomocą Arrays.stream() przekształci tablicę w prymitywną specjalizację Stream:

int[] intArr = {1, 2, 3};
IntStream intStream = Arrays.stream(intArr);

Możesz również ograniczyć Stream do zakresu elementów w tablicy. Indeks początkowy jest włącznie, a indeks końcowy jest wyłączny:

int[] values = {1, 2, 3, 4};
IntStream intStream = Arrays.stream(values, 2, 4);

Metoda podobna do Arrays.stream() pojawia się w klasie Stream : Stream.of() . Różnica polega na tym, że Stream.of() używa parametru varargs, więc możesz napisać coś takiego:

Stream<Integer> intStream = Stream.of(1, 2, 3);
Stream<String> stringStream = Stream.of("1", "2", "3");
Stream<Double> doubleStream = Stream.of(new Double[]{1.0, 2.0});

Iterowanie po tablicach

Możesz iterować po tablicach, używając rozszerzonej pętli for (aka foreach) lub indeksów tablicowych:

int[] array = new int[10];

// using indices: read and write
for (int i = 0; i < array.length; i++) {
    array[i] = i;
}
Java SE 5
// extended for: read only
for (int e : array) {
    System.out.println(e);
}

Warto tutaj zauważyć, że nie ma bezpośredniego sposobu na użycie Iteratora na tablicy, ale poprzez bibliotekę Arrays można go łatwo przekonwertować na listę, aby uzyskać obiekt Iterable .

W przypadku tablic w ramkach użyj Arrays.asList :

Integer[] boxed = {1, 2, 3};
Iterable<Integer> boxedIt = Arrays.asList(boxed); // list-backed iterable
Iterator<Integer> fromBoxed1 = boxedIt.iterator();

W przypadku prymitywnych tablic (przy użyciu języka Java 8) użyj strumieni (szczególnie w tym przykładzie - Arrays.stream -> IntStream ):

int[] primitives = {1, 2, 3};
IntStream primitiveStream = Arrays.stream(primitives); // list-backed iterable
PrimitiveIterator.OfInt fromPrimitive1 = primitiveStream.iterator();

Jeśli nie możesz używać strumieni (bez Java 8), możesz użyć biblioteki guava Google:

Iterable<Integer> fromPrimitive2 = Ints.asList(primitives);

W tablicach dwuwymiarowych lub więcej obie techniki mogą być stosowane w nieco bardziej złożony sposób.

Przykład:

int[][] array = new int[10][10];

for (int indexOuter = 0; indexOuter < array.length; indexOuter++) {
    for (int indexInner = 0; indexInner < array[indexOuter].length; indexInner++) {
        array[indexOuter][indexInner] = indexOuter + indexInner;
    }
}
Java SE 5
for (int[] numbers : array) {
    for (int value : numbers) {
        System.out.println(value);
    }
}

Niemożliwe jest ustawienie tablicy na jakąkolwiek nierównomierną wartość bez użycia pętli opartej na indeksie.

Oczywiście można także używać pętli while lub do-while podczas iteracji za pomocą indeksów.

Jedna uwaga: podczas korzystania z indeksów tablic upewnij się, że indeks zawiera się między 0 a array.length - 1 (obie włącznie). Nie rób sztywnych założeń dotyczących długości tablicy, w przeciwnym razie możesz złamać kod, jeśli długość tablicy się zmieni, ale twoje wartości zapisane na stałe nie.

Przykład:

int[] numbers = {1, 2, 3, 4};

public void incrementNumbers() {
    // DO THIS :
    for (int i = 0; i < numbers.length; i++) {
        numbers[i] += 1; //or this: numbers[i] = numbers[i] + 1; or numbers[i]++;      
    }
 
    // DON'T DO THIS :
    for (int i = 0; i < 4; i++) {
        numbers[i] += 1;
    }
}

Najlepiej jest również, jeśli nie używasz fantazyjnych obliczeń, aby uzyskać indeks, ale użyj indeksu do iteracji i jeśli potrzebujesz różnych wartości, oblicz je.

Przykład:

public void fillArrayWithDoubleIndex(int[] array) {
    // DO THIS :
    for (int i = 0; i < array.length; i++) {
        array[i] = i * 2;
    }
 
    // DON'T DO THIS :
    int doubleLength = array.length * 2;
    for (int i = 0; i < doubleLength; i += 2) {
        array[i / 2] = i;
    }
}

Dostęp do tablic w odwrotnej kolejności

int[] array = {0, 1, 1, 2, 3, 5, 8, 13};
for (int i = array.length - 1; i >= 0; i--) {
   System.out.println(array[i]);
}

Korzystanie z tablic tymczasowych w celu zmniejszenia liczby powtórzeń kodu

Iteracja tymczasowej tablicy zamiast powtarzania kodu może sprawić, że kod będzie czystszy. Może być stosowany, gdy ta sama operacja jest wykonywana na wielu zmiennych.

// we want to print out all of these
String name = "Margaret";
int eyeCount = 16;
double height = 50.2;
int legs = 9;
int arms = 5;


// copy-paste approach:
System.out.println(name);
System.out.println(eyeCount);
System.out.println(height);
System.out.println(legs);
System.out.println(arms);


// temporary array approach:
for(Object attribute : new Object[]{name, eyeCount, height, legs, arms})
    System.out.println(attribute);

// using only numbers
for(double number : new double[]{eyeCount, legs, arms, height})
    System.out.println(Math.sqrt(number));

Należy pamiętać, że tego kodu nie należy używać w sekcjach krytycznych pod względem wydajności, ponieważ tablica jest tworzona za każdym razem, gdy pętla jest wprowadzana, i że zmienne pierwotne zostaną skopiowane do tablicy, a zatem nie można ich modyfikować.

Kopiowanie tablic

Java zapewnia kilka sposobów kopiowania tablicy.

dla pętli

int[] a = { 4, 1, 3, 2 };
int[] b = new int[a.length]; 
for (int i = 0; i < a.length; i++) {
    b[i] = a[i];
}

Zauważ, że użycie tej opcji z tablicą Object zamiast pierwotnej spowoduje wypełnienie kopii odniesieniem do oryginalnej treści zamiast jej kopii.

Object.clone ()

Ponieważ tablice są Object w Javie, możesz użyć Object.clone() .

int[] a = { 4, 1, 3, 2 };
int[] b = a.clone(); // [4, 1, 3, 2]

Zauważ, że metoda Object.clone dla tablicy wykonuje płytką kopię , tzn. Zwraca odwołanie do nowej tablicy, która odwołuje się do tych samych elementów, co tablica źródłowa.


Arrays.copyOf ()

java.util.Arrays zapewnia łatwy sposób wykonania kopii tablicy na inną. Oto podstawowe zastosowanie:

int[] a = {4, 1, 3, 2};
int[] b = Arrays.copyOf(a, a.length); // [4, 1, 3, 2]

Zauważ, że Arrays.copyOf zapewnia również przeciążenie, które pozwala zmienić typ tablicy:

Double[] doubles = { 1.0, 2.0, 3.0 };
Number[] numbers = Arrays.copyOf(doubles, doubles.length, Number[].class);

System.arraycopy ()

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) Kopiuje tablicę z określonej tablicy źródłowej, zaczynając od określonej pozycji, do określonej pozycji tablicy docelowej.

Poniżej przykład użycia

int[] a = { 4, 1, 3, 2 };
int[] b = new int[a.length];
System.arraycopy(a, 0, b, 0, a.length); // [4, 1, 3, 2]

Arrays.copyOfRange ()

Używany głównie do kopiowania części tablicy, możesz go również użyć do skopiowania całej tablicy do innej, jak poniżej:

int[] a = { 4, 1, 3, 2 };
int[] b = Arrays.copyOfRange(a, 0, a.length); // [4, 1, 3, 2]

Rzucanie tablic

Tablice są obiektami, ale ich typ jest określony przez rodzaj zawartych obiektów. Dlatego nie można po prostu rzucić A[] na T[] , ale każdy element A[] konkretnego A[] musi być rzutowany na obiekt T Ogólny przykład:

public static <T, A> T[] castArray(T[] target, A[] array) {
    for (int i = 0; i < array.length; i++) {
        target[i] = (T) array[i];
    }
    return target;
}

Zatem biorąc pod uwagę tablicę A[] :

T[] target = new T[array.Length];
target = castArray(target, array);

Java SE udostępnia w tym celu metodę Arrays.copyOf(original, newLength, newType) :

Double[] doubles = { 1.0, 2.0, 3.0 };
Number[] numbers = Arrays.copyOf(doubles, doubles.length, Number[].class);

Usuń element z tablicy

Java nie zapewnia bezpośredniej metody w java.util.Arrays do usuwania elementu z tablicy. Aby go wykonać, możesz albo skopiować oryginalną tablicę na nową bez elementu do usunięcia, albo przekonwertować tablicę na inną strukturę umożliwiającą usunięcie.

Korzystanie z ArrayList

Możesz przekonwertować tablicę na java.util.List , usunąć element i przekonwertować listę z powrotem na tablicę w następujący sposób:

String[] array = new String[]{"foo", "bar", "baz"};

List<String> list = new ArrayList<>(Arrays.asList(array));
list.remove("foo");

// Creates a new array with the same size as the list and copies the list
// elements to it.
array = list.toArray(new String[list.size()]);

System.out.println(Arrays.toString(array)); //[bar, baz]

Korzystanie z System.arraycopy

System.arraycopy() można wykorzystać do wykonania kopii oryginalnej tablicy i usunięcia żądanego elementu. Poniżej przykład:

int[] array = new int[] { 1, 2, 3, 4 }; // Original array.
int[] result = new int[array.length - 1]; // Array which will contain the result.
int index = 1; // Remove the value "2".

// Copy the elements at the left of the index.
System.arraycopy(array, 0, result, 0, index);
// Copy the elements at the right of the index.
System.arraycopy(array, index + 1, result, index, array.length - index - 1);

System.out.println(Arrays.toString(result)); //[1, 3, 4]

Korzystanie z Apache Commons Lang

Aby łatwo usunąć element, możesz użyć biblioteki Apache Commons Lang, a zwłaszcza statycznej metody removeElement() klasy ArrayUtils . Poniżej przykład:

int[] array = new int[]{1,2,3,4};
array = ArrayUtils.removeElement(array, 2); //remove first occurrence of 2
System.out.println(Arrays.toString(array)); //[1, 3, 4]

Tablica kowariancji

Tablice obiektów są kowariantne, co oznacza, że tak jak Liczba Integer jest podklasą liczby, tak Number Integer[] jest podklasą liczby Number[] . Może się to wydawać intuicyjne, ale może powodować zaskakujące zachowanie:

Integer[] integerArray = {1, 2, 3};
Number[] numberArray = integerArray;  // valid
Number firstElement = numberArray[0]; // valid
numberArray[0] = 4L;                  // throws ArrayStoreException at runtime

Chociaż liczba Integer[] jest podklasą liczby Number[] , może przechowywać tylko liczby Integer , a próba przypisania elementu Long zgłasza wyjątek czasu wykonywania.

Zauważ, że takie zachowanie jest unikalne dla tablic i można tego uniknąć, używając zamiast tego ogólnej List :

List<Integer> integerList = Arrays.asList(1, 2, 3);
//List<Number> numberList = integerList;  // compile error
List<? extends Number> numberList = integerList;
Number firstElement = numberList.get(0);
//numberList.set(0, 4L);                  // compile error

Nie jest konieczne, aby wszystkie elementy tablicy miały ten sam typ, o ile są one podklasą typu tablicy:

interface I {}

class A implements I {}
class B implements I {}
class C implements I {}

I[] array10 = new I[] { new A(), new B(), new C() }; // Create an array with new
                                                     // operator and array initializer.

I[] array11 = { new A(), new B(), new C() };         // Shortcut syntax with array
                                                     // initializer.

I[] array12 = new I[3];                              // { null, null, null }

I[] array13 = new A[] { new A(), new A() };          // Works because A implements I.

Object[] array14 = new Object[] { "Hello, World!", 3.14159, 42 }; // Create an array with
                                                     // new operator and array initializer.

Object[] array15 = { new A(), 64, "My String" };     // Shortcut syntax 
                                                     // with array initializer.

Jak zmienić rozmiar tablicy?

Prosta odpowiedź brzmi: nie możesz tego zrobić. Po utworzeniu tablicy nie można zmienić jej rozmiaru. Zamiast tego można zmienić rozmiar tablicy tylko poprzez utworzenie nowej tablicy o odpowiednim rozmiarze i skopiowanie elementów z istniejącej tablicy do nowej.

String[] listOfCities = new String[3];   // array created with size 3.
listOfCities[0] = "New York";
listOfCities[1] = "London";
listOfCities[2] = "Berlin";

Załóżmy (na przykład), że należy dodać nowy element do tablicy listOfCities zdefiniowanej jak powyżej. Aby to zrobić, musisz:

  1. utwórz nową tablicę o rozmiarze 4,
  2. skopiuj istniejące 3 elementy starej tablicy do nowej tablicy z przesunięciem 0, 1 i 2 oraz
  3. dodaj nowy element do nowej tablicy z przesunięciem 3.

Można to zrobić na różne sposoby. Przed wersją Java 6 najbardziej zwięzłym sposobem było:

String[] newArray = new String[listOfCities.length + 1];
System.arraycopy(listOfCities, 0, newArray, 0, listOfCities.length);
newArray[listOfCities.length] = "Sydney";

Począwszy od Java 6, metody Arrays.copyOf i Arrays.copyOfRange mogą to zrobić w Arrays.copyOfRange sposób:

String[] newArray = Arrays.copyOf(listOfCities, listOfCities.length + 1);
newArray[listOfCities.length] = "Sydney";

Inne sposoby kopiowania tablicy znajdują się w następującym przykładzie. Pamiętaj, że podczas zmiany rozmiaru potrzebujesz kopii tablicy o innej długości niż oryginał.

Lepsze alternatywy dla zmiany rozmiaru tablicy

Istnieją dwie główne wady związane ze zmianą rozmiaru tablicy, jak opisano powyżej:

  • To jest nieefektywne. Zwiększanie lub zmniejszanie tablicy wymaga kopiowania wielu lub wszystkich istniejących elementów tablicy i przydzielania nowego obiektu tablicy. Im większa matryca, tym droższa.
  • Musisz być w stanie zaktualizować wszystkie „aktywne” zmienne, które zawierają odniesienia do starej tablicy.

Jedną z możliwości jest utworzenie tablicy o wystarczająco dużym rozmiarze na początek. Jest to wykonalne tylko wtedy, gdy można dokładnie określić ten rozmiar przed przydzieleniem tablicy . Jeśli nie możesz tego zrobić, problem zmiany rozmiaru tablicy pojawia się ponownie.

Inną alternatywą jest użycie klasy struktury danych dostarczonej przez bibliotekę klas Java SE lub bibliotekę innej firmy. Na przykład środowisko „kolekcje” Java SE zapewnia szereg implementacji interfejsów API List , Set i Map o różnych właściwościach środowiska wykonawczego. Klasa ArrayList jest najbliższa charakterystyce wydajności zwykłej tablicy (np. Wyszukiwanie O (N), pobieranie i ustawianie O (1), losowe wstawianie i usuwanie O (N)), zapewniając jednocześnie bardziej wydajną zmianę rozmiaru bez problemu z aktualizacją odniesienia.

(Wydajność zmiany rozmiaru dla ArrayList wynika ze strategii podwojenia rozmiaru macierzy bazowej przy każdej zmianie rozmiaru. W typowym przypadku użycia oznacza to, że zmieniasz rozmiar tylko od czasu do czasu. Kiedy amortyzujesz przez cały okres istnienia listy, koszt zmiany rozmiaru na wstawkę jest O(1) . Może być możliwe zastosowanie tej samej strategii podczas zmiany rozmiaru prostej tablicy.)

Znajdowanie elementu w tablicy

Istnieje wiele sposobów znalezienia położenia wartości w tablicy. W poniższych przykładowych fragmentach założono, że tablica jest jedną z następujących czynności:

  String[] strings = new String[] { "A", "B", "C" };
  int[] ints = new int[] { 1, 2, 3, 4 };

Ponadto każdy z nich ustawia index lub index2 na indeks wymaganego elementu lub -1 jeśli element nie jest obecny.

Korzystanie z Arrays.binarySearch (tylko dla sortowanych tablic)

  int index = Arrays.binarySearch(strings, "A");
  int index2 = Arrays.binarySearch(ints, 1);

Korzystanie z Arrays.asList (tylko w przypadku tablic innych niż pierwotne)

  int index = Arrays.asList(strings).indexOf("A");
  int index2 = Arrays.asList(ints).indexOf(1);  // compilation error

Korzystanie ze Stream

Java SE 8
  int index = IntStream.range(0, strings.length)
                       .filter(i -> "A".equals(strings[i]))
                       .findFirst()
                       .orElse(-1); // If not present, gives us -1.
  // Similar for an array of primitives

Wyszukiwanie liniowe za pomocą pętli

  int index = -1;
  for (int i = 0; i < array.length; i++) {
      if ("A".equals(array[i])) {
          index = i;
          break;
      }            
  }
  // Similar for an array of primitives

Wyszukiwanie liniowe przy użyciu bibliotek innych firm, takich jak org.apache.commons

  int index = org.apache.commons.lang3.ArrayUtils.contains(strings, "A");
  int index2 = org.apache.commons.lang3.ArrayUtils.contains(ints, 1);

Uwaga: Korzystanie z bezpośredniego wyszukiwania liniowego jest bardziej wydajne niż zawijanie listy.

Testowanie, czy tablica zawiera element

Powyższe przykłady można dostosować do testowania, czy tablica zawiera element, po prostu testując, czy obliczony indeks jest większy czy równy zero.

Alternatywnie istnieją również bardziej zwięzłe warianty:

boolean isPresent = Arrays.asList(strings).contains("A");
Java SE 8
boolean isPresent = Stream<String>.of(strings).anyMatch(x -> "A".equals(x));
boolean isPresent = false;
for (String s : strings) {
    if ("A".equals(s)) {
        isPresent = true;
        break;
    }
}

boolean isPresent = org.apache.commons.lang3.ArrayUtils.contains(ints, 4);

Sortowanie tablic

Sortowanie tablic można łatwo wykonać za pomocą interfejsu API tablic .

import java.util.Arrays;

// creating an array with integers
int[] array = {7, 4, 2, 1, 19};
// this is the sorting part just one function ready to be used
Arrays.sort(array);
// prints [1, 2, 4, 7, 19]
System.out.println(Arrays.toString(array));

Sortowanie tablic łańcuchowych:

String nie jest danymi liczbowymi, określa własny porządek, który nazywa się porządkiem leksykograficznym, znanym również jako porządek alfabetyczny. Kiedy sortujesz tablicę String przy użyciu metody sort() , sortuje tablicę w naturalnej kolejności zdefiniowanej przez interfejs Porównywalny, jak pokazano poniżej:

Rosnące zamówienie

String[] names = {"John", "Steve", "Shane", "Adam", "Ben"};
System.out.println("String array before sorting : " + Arrays.toString(names));
Arrays.sort(names); 
System.out.println("String array after sorting in ascending order : " + Arrays.toString(names));

Wynik:

String array before sorting : [John, Steve, Shane, Adam, Ben]    
String array after sorting in ascending order : [Adam, Ben, John, Shane, Steve]

Malejący porządek

Arrays.sort(names, 0, names.length, Collections.reverseOrder());
System.out.println("String array after sorting in descending order : " + Arrays.toString(names));

Wynik:

String array after sorting in descending order : [Steve, Shane, John, Ben, Adam]

Sortowanie tablicy obiektów

Aby posortować tablicę obiektów, wszystkie elementy muszą implementować interfejs Comparable lub Comparator , aby zdefiniować kolejność sortowania.

Możemy użyć dowolnej metody sort(Object[]) , aby posortować tablicę obiektów w jej naturalnej kolejności, ale musisz upewnić się, że wszystkie elementy w tablicy muszą implementować wartość Comparable .

Ponadto muszą być one również wzajemnie porównywalne, na przykład e1.compareTo(e2) nie może ClassCastException dla żadnych elementów e1 i e2 w tablicy. Alternatywnie możesz sortować tablicę obiektów według niestandardowej kolejności, używając metody sort(T[], Comparator) , jak pokazano w poniższym przykładzie.

// How to Sort Object Array in Java using Comparator and Comparable
Course[] courses = new Course[4];
courses[0] = new Course(101, "Java", 200);
courses[1] = new Course(201, "Ruby", 300);
courses[2] = new Course(301, "Python", 400);
courses[3] = new Course(401, "Scala", 500);
       
System.out.println("Object array before sorting : " + Arrays.toString(courses));
       
Arrays.sort(courses);
System.out.println("Object array after sorting in natural order : " + Arrays.toString(courses));
       
Arrays.sort(courses, new Course.PriceComparator());
System.out.println("Object array after sorting by price : " + Arrays.toString(courses));
       
Arrays.sort(courses, new Course.NameComparator());
System.out.println("Object array after sorting by name : " + Arrays.toString(courses));

Wynik:

Object array before sorting : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 , #401 Scala@500 ]    
Object array after sorting in natural order : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 , #401 Scala@500 ]    
Object array after sorting by price : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 , #401 Scala@500 ]    
Object array after sorting by name : [#101 Java@200 , #301 Python@400 , #201 Ruby@300 , #401 Scala@500 ]

Konwertowanie tablic między operacjami podstawowymi i typami pudełkowymi

Czasami konieczna jest konwersja typów pierwotnych na typy pudełkowe .

Aby przekonwertować tablicę, można użyć strumieni (w Javie 8 i nowszych):

Java SE 8
int[] primitiveArray = {1, 2, 3, 4};
Integer[] boxedArray = 
    Arrays.stream(primitiveArray).boxed().toArray(Integer[]::new);

W przypadku niższych wersji może to być iteracja pierwotnej tablicy i jawne skopiowanie jej do tablicy w ramce:

Java SE 8
int[] primitiveArray = {1, 2, 3, 4};
Integer[] boxedArray = new Integer[primitiveArray.length];
for (int i = 0; i < primitiveArray.length; ++i) {
    boxedArray[i] = primitiveArray[i]; // Each element is autoboxed here
}

Podobnie tablicę pudełkową można przekonwertować na tablicę jej prymitywnego odpowiednika:

Java SE 8
Integer[] boxedArray = {1, 2, 3, 4};
int[] primitiveArray = 
    Arrays.stream(boxedArray).mapToInt(Integer::intValue).toArray();
Java SE 8
Integer[] boxedArray = {1, 2, 3, 4};
int[] primitiveArray = new int[boxedArray.length];
for (int i = 0; i < boxedArray.length; ++i) {
    primitiveArray[i] = boxedArray[i]; // Each element is outboxed here
}


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow