John Squirrels
רָמָה
San Francisco

Java Vector

פורסם בקבוצה
כנראה שכבר נתקלתם במערכים בג'אווה, ואתם יודעים שאחד החסרונות העיקריים שלהם הוא קביעות הגודל. לאחר שיצרת מערך בגודל מסוים, לא תוכל לשנות זאת מאוחר יותר. ישנן מספר מחלקות מסגרת Java Collection בשפת Java שפותרות בעיה זו. אחד מהם הוא Java Vector Class. זה יידון במאמר זה.

מה זה וקטור Class

כפי שכתבנו בהקדמה, מחלקת Vector מ-Java Collection Framework מבטלת את בעיית הגודל הסטטי של מערכים. Java Vector הוא סוג של מערך דינמי ויכול לגדול או להתכווץ בגודלו. באמצעות המחלקה Vector collection, אנו יכולים לאחסן קבוצת אלמנטים כאובייקטים פשוטים ולתפעל אותם באמצעות השיטות השונות. המחלקה Vector זמינה מחבילת java.util . לפיכך, ניתן להשתמש בוקטור בג'אווה אם אינך יודע את גודל המערך מראש, או אם אתה זקוק ל"מערך" שיכול לשנות ממדים לאורך חיי התוכנית. יש לומר מיד שמחלקת וקטור כבר די ישנה, ​​והופיעו מאוחר יותר אוספים שיכולים להחליף אותה ברוב המכריע של המקרים. ה"אנלוגי" הפופולרי של Java Vector הוא המחלקה ArrayList . ההבדל החשוב ביותר בין המחלקות הללו זה מזה הוא ש-Vector מסונכרן, בעוד ArrayList לא. נדבר על הבדלים אחרים בין שתי המחלקות הללו ועל אנלוגים מודרניים יותר של מחלקת וקטור מעט מאוחר יותר בסעיף "מה לא בסדר עם מחלקת וקטור".

Java Vector Methods

להלן שיטות Java Vector :
  • void add(int index, Object element) מכניס את האלמנט שצוין במיקום המצוין של הווקטור.

  • boolean add(Object o) מוסיף את האלמנט שצוין לסוף הווקטור.

  • boolean addAll(Collection c) מוסיף את כל האלמנטים באוסף שצוין לסוף הווקטור, בסדר שהם מוחזרים על ידי איטרטור האוסף שצוין.

  • boolean addAll(int index, Collection c) מוסיף את כל האלמנטים בתוך האוסף שצוין לוקטור במיקום שצוין.

  • void addElement(Object obj) מוסיף את הרכיב שצוין לסוף הווקטור הזה, מגדיל את גודלו באחד.

  • int capacity() מחזירה את הקיבולת הנוכחית של וקטור זה.

  • void clear() מסיר את כל האלמנטים מהוקטור הזה.

  • Object clone() מחזיר שיבוט של וקטור זה.

  • boolean contains(Object elem) בודק אם האובייקט שצוין הוא רכיב בוקטור זה.

  • boolean containsAll(Collection c) מחזירה true אם הווקטור מכיל את כל האלמנטים של האוסף שצוין.

  • void copyInto(Object[] anArray) מעתיק את הרכיבים של וקטור זה למערך שצוין.

  • Object elementAt(int index) מחזיר את הרכיב באינדקס שצוין.

  • Enumeration elements() מחזירה ספירה של הרכיבים של וקטור זה.

  • void sureCapacity(int minCapacity) מגדיל את הקיבולת של וקטור זה, במידת הצורך, כדי להבטיח שהוא יכול להחזיק לפחות את מספר הרכיבים שניתן על ידי ארגומנט הקיבולת המינימלית.

  • boolean equals(Object o) משווה את האובייקט שצוין לוקטור זה.

  • Object firstElement() מחזיר את הרכיב הראשון (אלמנט באינדקס 0) של הווקטור הזה.

  • Object get(int index) מחזיר את האלמנט במיקום שצוין בוקטור זה.

  • int hashCode() מחזירה את ערך קוד ה-hash עבור וקטור זה.

  • int indexOf(Object elem) מחפש את המופע הראשון של הארגומנט הנתון, בודק שוויון בשיטת equals.

  • int indexOf(Object elem, int index) מחפש את ההופעה הראשונה של הארגומנט הנתון, החל באינדקס, ובודק שוויון בשיטת equals.

  • void insertElementAt(Object obj, int index) מכניס את האובייקט שצוין כרכיב לוקטור זה באינדקס שצוין.

  • boolean isEmpty() בודק את הווקטור הזה עבור רכיבים חסרים.

  • אובייקט lastElement() מחזיר את הרכיב האחרון של הווקטור.

  • int lastIndexOf(Object elem) מחזירה את האינדקס של המופע האחרון של האובייקט שצוין בוקטור זה.

  • int lastIndexOf(Object elem, int index) מחפש לאחור את האובייקט שצוין, החל מהאינדקס שצוין, ומחזיר אליו את האינדקס.

  • Object remove(int index) מסיר את האלמנט במיקום שצוין בוקטור זה.

  • boolean remove(Object o) מסיר את המופע הראשון של האלמנט שצוין בוקטור זה. אם הווקטור אינו מכיל אלמנט, הוא לא משתנה.

  • boolean removeAll(Collection c) מסיר את כל האלמנטים מהווקטור הכלולים באוסף שצוין.

  • void removeAllElements() מסיר את כל הרכיבים מהווקטור ומגדיר את גודלו לאפס.

  • boolean removeElement(Object obj) מסיר את המופע הראשון (האינדקס הנמוך ביותר) של הארגומנט מהוקטור הזה.

  • void removeElementAt(int index) מסיר אלמנט ב- index.

  • protected void removeRange(int fromIndex, int toIndex) מסיר מהרשימה הזו את כל הרכיבים שהאינדקס שלהם נמצא בין fromIndex, כולל, ו-toIndex, באופן בלעדי.

  • boolean retainAll(Collection c) שומר רק על האלמנטים בוקטור הכלולים באוסף שצוין.

  • Object set (int index, Object element) מחליף את האלמנט במיקום שצוין בוקטור זה באלמנט שצוין.

  • void setElementAt(Object obj, int index) מגדיר את הרכיב באינדקס שצוין של וקטור זה כאובייקט הנתון.

  • void setSize(int newSize) מגדיר את הגודל של וקטור זה.

  • int size() מחזירה את מספר הרכיבים בוקטור זה.

  • List subList(int fromIndex, int toIndex) מחזיר ייצוג (תצוגה) של החלק של רשימה זו בין fromIndex, כולל, ו-toIndex, באופן בלעדי.

  • Object[] toArray() מחזיר מערך המכיל את כל הרכיבים של הווקטור הזה בסדר הנכון.

  • Object[] toArray(Object[] a) מחזיר מערך המכיל את כל האלמנטים של וקטור זה בסדר הנכון; סוג הביצוע של המערך המוחזר הוא סוג המערך שצוין.

  • String toString() מחזירה ייצוג מחרוזת של וקטור זה המכילה ייצוג מחרוזת של כל אלמנט.

  • void trimToSize() חותך את הקיבולת של וקטור זה לגודל הנוכחי של הווקטור.

דוגמה וקטורית של 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());

   }
}
הפלט של תוכנית זו נמצא כאן למטה:
גודל הווקטור הריק = 0 [ג'וני, אייבי, ריקי] [ג'וני, אייבי, ריקי, ג'וני, פול] גודל הווקטור = 5 האלמנט הראשון של הווקטור = ג'וני 0 3 גודל הווקטור לאחר ברור שיטה = 0

מה רע ב-Vector Class?

על פי התיעוד של מחלקת Java Vector , אם אינך זקוק למימוש בטוח בשרשור בתוכנית שלך, מומלץ להשתמש ב- ArrayList במקום Vector (משתתף יעיל יותר ב-Collection Framework). בואו נשנה מעט את הדוגמה למעלה, באמצעות המחלקה ArrayList במקום 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());

       }
   }
הערנו את השורה עם vector.indexOf("Johnny", 1) , כי אין שיטה כזו בווריאציה זו במחלקה ArrayList . מאותה סיבה, שורת vector.firstElement() הוסרה הערות. מכל הבחינות האחרות, התוכנית מפיקה את אותה תוצאה כמו הראשונה. כמובן, בדוגמה כזו, לא ברור מדוע ArrayList עדיף על וקטור . זה דורש יותר ידע על, למשל, שרשורים. אנו מפרטים את הסיבות כאן. ראשית, למרות שהמחלקה הווקטורית מסונכרנת, לא ניתן לכנות אותה בטוחה לחלוטין לשרשור, למרות שזה נראה מוזר. העובדה היא שוקטור מסנכרן כל פעולה, לא את כל מופע הוקטור עצמו. זו יכולה להיות בעיה בתוכניות שבהן אתה צריך לסנכרן את כל מערך הפעולות ולא פעולות בודדות. נניח, אם שרשור אחד חוזר על וקטור ושרשור אחר משנה באופן מבני מופע של הווקטור, האיטרטור יזרוק ConcurrentModificationException . מסתבר ששני פתילים יכולים לעבוד עם מופע וקטור בו זמנית אם הם מבצעים פעולות שונות. שנית, למחלקה Vector אין את הביצועים הטובים ביותר מכיוון שלאובייקטים שלה יש מערך וסנכרון שניתן לשנות את גודלו. שילוב זה פירושו תקורה נוספת לחסימת פעולות, בין אם נדרש סנכרון או לא. בטח, זה משפיע על הביצועים. בנוסף, לסינכרון הווקטור בכל פעולה יש גם השפעה שלילית על הביצועים, שכן נרכוש נעילה שוב ושוב עבור כל פעולה. אם כל המופע של המחלקה היה מסונכרן, אז גם המנעול היה נרכש פעם אחת, וזה הרבה יותר יעיל. שלישית, וקטור תומך בכמה שיטות מדור קודם. לדוגמה elements() . שיטה זו מחזירה ספירה של מרכיבי הווקטור. מתכנתים משתמשים לרוב ב-Iterator או ListIterator ל-Enumeration, וממספר סיבות. במיוחד, ל-Enumeration אין שיטת remove() מוגדרת, מה שאומר שלא ניתן לשנות את הרשימה באופן מבני במהלך האיטרציה. כמו כן, שלא כמו ListIterator, Enumeration אינה מציעה גישה דו-כיוונית. כפי שאתה יכול לראות, ל-Vector יש לא מעט בעיות. מה אם אתה עדיין צריך יישום בטוח בשרשור של ממשק List? במקרה זה, ArrayList לא יעזור, אבל אתה יכול להשתמש, למשל, במחלקה CopyOnWriteArrayList במקום Vector ; הוא ממוקם כגרסה בטוחה לשרשור של ArrayList . אתה יכול גם לסנכרן את ArrayList באמצעות האוספיםשיטת synchronizedList() .

לווקטור באמת יש כמה בעיות... למה זה עדיין בג'אווה ולמה צריך ללמד אותו?

נשאלת השאלה: למה אנחנו לומדים בכלל את כיתת וקטור ? ולמה זה עדיין לא הוסר מג'אווה? העובדה היא ש-Java מצהירה על העיקרון של תאימות לאחור. המשמעות היא שכל הקוד הישן שנכתב לפני שנים רבות יובן על ידי גרסאות מודרניות של Java. בנוסף, ישנן לא מעט יישומים ברמת הארגון בסביבת Java שנתמכו כבר עשרות שנים. בהחלט יתכן שתצטרך להתמודד עם "דינוזאור" כזה בעבודה שלך, אז אתה צריך להיות מוכן להפתעות, כמו קוד עם שיעורי מורשת לא יעילים.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION