CodeGym /Blog Java /Random-PL /Wektor Java
Autor
Artem Divertitto
Senior Android Developer at United Tech

Wektor Java

Opublikowano w grupie Random-PL
Zapewne spotkałeś się już z tablicami w Javie i wiesz, że jedną z ich głównych wad jest stałość rozmiaru. Po utworzeniu tablicy o określonym rozmiarze nie można jej później zmienić. Istnieje kilka klas frameworka Java Collection w języku Java, które rozwiązują ten problem. Jednym z nich jest Java Vector Class. Zostanie to omówione w tym artykule.

Co to jest klasa Vector

Jak pisaliśmy we wstępie, klasa Vector z Java Collection Framework eliminuje problem statycznego rozmiaru tablic. Java Vector to rodzaj dynamicznej tablicy, której rozmiar może się zwiększać lub zmniejszać. Korzystając z klasy kolekcji Vector , możemy przechowywać grupę elementów jako proste obiekty i manipulować nimi za pomocą różnych metod. Klasa Vector jest dostępna z pakietu java.util . Tak więc Vector w Javie może być używany, jeśli nie znasz wcześniej rozmiaru tablicy lub potrzebujesz „tablicy”, która może zmieniać wymiary w trakcie życia programu. Trzeba od razu powiedzieć, że Vectorklasa jest już dość stara i pojawiły się późniejsze kolekcje, które w zdecydowanej większości przypadków mogą ją zastąpić. Popularnym „analogiem” Java Vector jest klasa ArrayList . Najważniejszą różnicą między tymi klasami jest to, że Vector jest zsynchronizowany, a ArrayList nie. O innych różnicach między tymi dwiema klasami i bardziej nowoczesnymi odpowiednikami klasy Vector porozmawiamy nieco później w sekcji „Co jest nie tak z klasą Vector”.

Metody wektorowe Javy

Oto metody wektorowe Java :
  • void add(int index, Object element) wstawia określony element w określonej pozycji wektora.

  • boolean add(Object o) dodaje określony element na koniec wektora.

  • boolean addAll(Collection c) dodaje wszystkie elementy w określonej kolekcji na koniec wektora, w kolejności, w jakiej są zwracane przez określony iterator kolekcji.

  • boolean addAll(int index, Collection c) wstawia wszystkie elementy z określonej kolekcji do wektora w określonej pozycji.

  • void addElement(Object obj) dodaje określony komponent na koniec tego wektora, zwiększając jego rozmiar o jeden.

  • int Capacity() zwraca aktualną pojemność tego wektora.

  • void clear() usuwa wszystkie elementy z tego wektora.

  • Obiekt clone() zwraca klon tego wektora.

  • logiczna zawiera(Object elem) sprawdza, czy określony obiekt jest komponentem w tym wektorze.

  • logiczna zawieraAll(Collection c) zwraca wartość true, jeśli wektor zawiera wszystkie elementy określonej kolekcji.

  • void copyInto(Object[] anArray) kopiuje komponenty tego wektora do określonej tablicy.

  • Object elementAt(int index) zwraca komponent o podanym indeksie.

  • Enumeration elements() zwraca wyliczenie składowych tego wektora.

  • void pewnieCapacity(int minCapacity) zwiększa pojemność tego wektora, jeśli to konieczne, aby upewnić się, że może pomieścić co najmniej liczbę komponentów określoną przez argument minimalnej pojemności.

  • boolean equals(Object o) porównuje określony obiekt z tym wektorem.

  • Obiekt firstElement() zwraca pierwszy składnik (element o indeksie 0) tego wektora.

  • Obiekt get(int index) zwraca element w określonej pozycji w tym wektorze.

  • int hashCode() zwraca wartość kodu skrótu dla tego wektora.

  • int indexOf(Object elem) wyszukuje pierwsze wystąpienie podanego argumentu, sprawdzając równość za pomocą metody equals.

  • int indexOf(Object elem, int index) wyszukuje pierwsze wystąpienie podanego argumentu, zaczynając od indeksu, i sprawdza równość za pomocą metody equals.

  • void insertElementAt(Object obj, int index) wstawia określony obiekt jako komponent do tego wektora pod określonym indeksem.

  • boolean isEmpty() sprawdza ten wektor pod kątem brakujących komponentów.

  • Obiekt lastElement() zwraca ostatni składnik wektora.

  • int lastIndexOf(Object elem) zwraca indeks ostatniego wystąpienia określonego obiektu w tym wektorze.

  • int lastIndexOf(Object elem, int index) wyszukuje wstecz określony obiekt, zaczynając od określonego indeksu, i zwraca mu indeks.

  • Object remove(int index) usuwa element w określonej pozycji w tym wektorze.

  • boolean remove(Object o) usuwa pierwsze wystąpienie określonego elementu w tym wektorze. Jeśli wektor nie zawiera elementu, nie zmienia się.

  • boolean removeAll(Collection c) usuwa wszystkie elementy z wektora, które są zawarte w określonej kolekcji.

  • void removeAllElements() usuwa wszystkie komponenty z wektora i ustawia jego rozmiar na zero.

  • boolean removeElement(Object obj) usuwa pierwsze (najniższy indeks) wystąpienie argumentu z tego wektora.

  • void removeElementAt(int index) usuwa element z indeksu.

  • protected void removeRange(int fromIndex, int toIndex) usuwa z tej Listy wszystkie elementy, których indeks jest pomiędzy fromIndex włącznie, a toIndex, wyłącznie.

  • boolean keepAll(Collection c) zachowuje tylko te elementy wektora, które są zawarte w określonej kolekcji.

  • Object set(int index, Object element) zastępuje element w określonej pozycji w tym wektorze określonym elementem.

  • void setElementAt(Object obj, int index) ustawia komponent o określonym indeksie tego wektora jako dany obiekt.

  • void setSize(int newSize) ustawia rozmiar tego wektora.

  • int size() zwraca liczbę komponentów w tym wektorze.

  • List subList(int fromIndex, int toIndex) zwraca reprezentację (widok) części tej listy pomiędzy fromIndex, włącznie, a toIndex, wyłącznie.

  • Object[] toArray() zwraca tablicę zawierającą wszystkie elementy tego wektora we właściwej kolejności.

  • Object[] toArray(Object[] a) zwraca tablicę zawierającą wszystkie elementy tego wektora we właściwej kolejności; typem wykonania zwróconej tablicy jest typ określonej tablicy.

  • Metoda String toString() zwraca łańcuchową reprezentację tego wektora zawierającą łańcuchową reprezentację każdego elementu.

  • void trimToSize() przycina pojemność tego wektora do aktualnego rozmiaru wektora.

Przykład wektora Java


import java.util.Vector;

public class VectorExample {

   public static void main(String[] args) {
       Vector vector = new Vector();
       System.out.println("the size of the empty vector = " +  vector.size());
       //adding some vector elements
       vector.add("Johnny");
       vector.add("Ivy");
       vector.add("Ricky");
       System.out.println(vector); 
       
       //adding more vector elements       
       vector.add("Johnny");
       vector.add("Paul");
       System.out.println(vector);
       System.out.println("the size of the vector = " +  vector.size());
       System.out.println("the first element of the vector = " + vector.firstElement());

       //here the program will print out the first appearance of "Johnny" element
       System.out.println(vector.indexOf("Johnny"));
       //program will print out the first appearance of "Johnny" element starting from the element 1
       System.out.println(vector.indexOf("Johnny", 1));
       vector.clear(); //deleting all vector elements
       System.out.println("the size of the vector after clear method = " +  vector.size());

   }
}
Wyjście tego programu jest tutaj poniżej:
rozmiar pustego wektora = 0 [Johnny, Ivy, Ricky] [Johnny, Ivy, Ricky, Johnny, Paul] rozmiar wektora = 5 pierwszy element wektora = Johnny 0 3 rozmiar wektora po usunięciu metoda = 0

Co jest nie tak z klasą Vector?

Zgodnie z dokumentacją klasy Java Vector , jeśli nie potrzebujesz implementacji wątkowo bezpiecznej w swoim programie, zaleca się użycie ArrayList zamiast Vector (bardziej efektywny uczestnik Collection Framework). Zmieńmy trochę powyższy przykład, używając klasy ArrayList zamiast Vector .

import java.util.ArrayList;
import java.util.List;

public class ArrayListExample {

       public static void main(String[] args) {
           List vector = new ArrayList();
           //Vector vector = new Vector();
           System.out.println("the size of the empty vector = " +  vector.size());
           vector.add("Johnny");
           vector.add("Ivy");
           vector.add("Ricky");
           System.out.println(vector);
           vector.add("Johnny");
           vector.add("Paul");
           System.out.println(vector);
           System.out.println("the size of the vector = " +  vector.size());
           //System.out.println("the first element of the vector = " + vector.firstElement());

           //here the program will print out the first appearance of "Johnny" element
           System.out.println(vector.indexOf("Johnny"));
           //program will print out the first appearance of "Johnny" element starting from the element 1
           //System.out.println(vector.indexOf("Johnny", 1));
           vector.clear();
           System.out.println("the size of the vector after clear method = " +  vector.size());

       }
   }
Skomentowaliśmy linię za pomocą vector.indexOf("Johnny", 1) , ponieważ w tej odmianie klasy ArrayList nie ma takiej metody . Z tego samego powodu linia vector.firstElement() została zakomentowana. Pod wszystkimi innymi względami program daje taki sam wynik jak pierwszy. Oczywiście w takim przykładzie nie jest jasne, dlaczego ArrayList jest lepszy niż Vector . Wymaga to większej wiedzy na temat, powiedzmy, wątków. Powody wymieniamy tutaj. Po pierwsze, chociaż klasa Vector jest zsynchronizowana, nie można jej nazwać całkowicie bezpieczną dla wątków, chociaż wydaje się to dziwne. Faktem jest, że Vector synchronizuje każdą operację, a nie cały Vectorsama instancja. Może to stanowić problem w programach, w których trzeba zsynchronizować cały zestaw operacji, a nie poszczególne operacje. Powiedzmy, że jeśli jeden wątek iteruje po wektorze, a inny wątek modyfikuje strukturalnie instancję wektora, iterator zgłosi wyjątek ConcurrentModificationException . Okazuje się, że dwa wątki mogą pracować z instancją Vector w tym samym czasie, jeśli wykonują różne operacje. Po drugie wektorclass nie ma najlepszej wydajności, ponieważ jej obiekty mają tablicę o zmiennym rozmiarze i synchronizację. Ta kombinacja oznacza dodatkowy narzut związany z operacjami blokowania, niezależnie od tego, czy synchronizacja jest wymagana, czy nie. Oczywiście wpływa to na wydajność. Ponadto synchronizacja wektora przy każdej operacji ma również negatywny wpływ na wydajność, ponieważ dla każdej operacji uzyskujemy blokadę raz za razem. Gdyby cała instancja klasy została zsynchronizowana, wówczas blokada zostałaby również uzyskana raz, co jest znacznie bardziej wydajne. Po trzecie, Vector obsługuje niektóre starsze metody. Na przykład elementy(). Ta metoda zwraca wyliczenie składników wektora. Programiści najczęściej używają Iteratora lub ListIteratora do wyliczenia iz wielu powodów. W szczególności Enumeration nie ma zdefiniowanej metody remove() , co oznacza, że ​​lista nie może być modyfikowana strukturalnie podczas iteracji. Ponadto, w przeciwieństwie do ListIterator, Enumeration nie oferuje dostępu dwukierunkowego. Jak widać, Vector ma sporo problemów. Co zrobić, jeśli nadal potrzebujesz bezpiecznej dla wątków implementacji interfejsu List? W tym przypadku ArrayList nie pomoże, ale możesz użyć na przykład klasy CopyOnWriteArrayList zamiast Vector ; jest umieszczony jako bezpieczny wątkowo wariant ArrayList. Listę ArrayList można również zsynchronizować za pomocą metody Collections synchronizedList() .

Vector naprawdę ma pewne problemy... dlaczego wciąż jest w Javie i dlaczego powinno się go uczyć?

Powstaje pytanie: po co w ogóle uczymy się klasy Vector ? I dlaczego nie został jeszcze usunięty z Javy? Faktem jest, że Java wyznaje zasadę kompatybilności wstecznej. Oznacza to, że cały stary kod napisany wiele lat temu będzie zrozumiały dla nowoczesnych wersji Javy. Ponadto istnieje sporo aplikacji klasy korporacyjnej w środowisku Java, które są obsługiwane od dziesięcioleci. Całkiem możliwe, że z takim „dinozaurem” będziesz miał do czynienia w swojej pracy, więc musisz być przygotowany na niespodzianki, takie jak kod z nieefektywnymi klasami legacy.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION