CodeGym /Java Blog /Toto sisi /Java 數組列表
John Squirrels
等級 41
San Francisco

Java 數組列表

在 Toto sisi 群組發布
你好!在之前的課程中,我們深入探討了數組並回顧了使用數組的常見示例。在本課中,我們將仔細回顧 Java ArrayList。通常,數組非常方便。而且,正如您已經註意到的那樣,您可以用它們做很多事情 :) 但是數組確實有很多缺點。
  • 尺寸有限。在創建數組時,您需要知道數組需要包含多少個元素。如果你低估了,那麼你將沒有足夠的空間。高估,數組將保持半空,這也很糟糕。畢竟,您分配的內存仍然比必要的多。

  • 數組沒有添加元素的方法。您必須始終明確指示要添加元素的位置的索引。如果你不小心指定了某個位置的索引被你需要的某個值佔用,它就會被覆蓋。

  • 沒有刪除項目的方法。一個值只能被“歸零”。

public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat[] cats = new Cat[3];
       cats[0] = new Cat("Thomas");
       cats[1] = new Cat("Behemoth");
       cats[2] = new Cat("Lionel Messi");

       cats[1] = null;

      
      
       System.out.println(Arrays.toString(cats));
   }

   @Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
輸出: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] 幸運的是,Java 的創建者很清楚數組的優點和缺點,因此創建了一個非常有趣的數據結構,稱為Java ArrayList。盡可能簡單地說,Java ArrayList是一個具有許多新特性的“增強型”數組。

如何創建數組列表

創建非常容易:

ArrayList<Cat> cats = new ArrayList<Cat>();
現在我們已經創建了一個用於存儲Cat對象 的列表。請注意,我們沒有指定ArrayList的大小,因為它可以自動擴展。這怎麼可能?其實很簡單。您可能會感到驚訝,但Java 中的 ArrayList是建立在一個非常普通的數組之上的:) 是的,它包含一個數組,這就是我們存儲元素的地方。但是Java 中的ArrayList有一種處理該數組的特殊方式:
  • 當內部數組被填充時,ArrayList 在內部創建一個新數組。新數組的大小是舊數組的大小乘以 1.5 加 1。

  • 所有數據都從舊數組複製到新數組中

  • 舊數組由垃圾收集器清理。
這種機制允許Java ArrayList(不同於普通數組)實現添加新元素的方法。這是add()方法

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<Cat>();
   cats.add(new Cat("Behemoth"));
}
新項目被添加到列表的末尾。現在沒有數組溢出的風險,所以這個方法是完全安全的。順便說一句,ArrayList不僅可以通過其索引查找對象,反之亦然:它可以使用引用在 ArrayList 中查找對象的索引!這就是indexOf()方法的用途:我們傳遞一個對我們想要的對象的引用,然後indexOf()返回它的索引:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   int thomasIndex = cats.indexOf(thomas);
   System.out.println(thomasIndex);
}
輸出: 0 沒錯。我們的thomas對象確實存儲在元素 0 中。數組不僅有缺點。他們也有不容置疑的優勢。其中之一是通過索引搜索元素的能力。因為我們指向一個索引,即指向一個特定的內存地址,所以以這種方式搜索數組非常快。ArrayList也知道怎麼做!get ()方法實現了這個:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   Cat secondCat = cats.get(1);

   System.out.println(secondCat);
}
輸出: Cat{name='Behemoth'} 此外,您可以輕鬆找出ArrayList是否包含特定對象。這是使用ArrayList contains() 方法完成的:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   cats.remove(fluffy);
   System.out.println(cats.contains(fluffy));
}
該方法檢查ArrayList的內部數組是否包含該元素,並返回一個布爾值(真或假)。輸出: false 還有一個關於插入的重要事情。 ArrayList使您不僅可以在數組末尾而且可以在任何位置使用索引來插入元素。 它有兩種方法:
  • ArrayList添加(整數索引,Cat 元素)
  • ArrayList set(int 索引, Cat 元素)
作為參數,這兩種方法都採用您要插入的位置的索引,以及對對象本身的引用。不同之處在於使用set()插入會覆蓋舊值。使用add()插入首先將 [index] 中的所有元素移動一個到數組的末尾,然後將指定的對象添加到生成的空位置。

這是一個例子:


public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);

   System.out.println(cats.toString());

   cats.set(0, lionel);// Now we have a list of 2 cats. Adding a 3rd using set

   System.out.println(cats.toString());
}
輸出: [[Cat{name='Thomas'}, Cat{name='Behemoth'}] [Cat{name='Lionel Messi'}, Cat{name='Behemoth'}] 我們有一個包含 2 隻貓的列表然後我們使用set()方法插入另一個作為元素 0 。結果,舊元素已被新元素替換。

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);

   System.out.println(cats.toString());

   cats.add(0, lionel);// Now we have a list of 2 cats. Adding a 3rd using add

   System.out.println(cats.toString());
}
在這裡我們看到add() 的工作方式不同。它將所有元素向右移動,然後將新值寫入元素 0。輸出: [Cat{name='Thomas'}, Cat{name='Behemoth'}] [Cat{name='Lionel Messi'}, Cat{name='Thomas'}, Cat{name='Behemoth'}] 要完全清除列表,我們使用clear()方法:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   cats.clear();

   System.out.println(cats.toString());
}
輸出: [] 一切都從列表中刪除。順便說一下,請注意:與數組不同,ArrayList重寫了toString()方法並且已經將列表適當地顯示為字符串。對於普通數組,我們必須為此使用Arrays類。由於我提到了Arrays:Java 讓您可以輕鬆地在數組和ArrayList之間“切換” ,即將一個轉換為另一個。Arrays為此提供了Arrays.asList()方法。我們用它來獲取內容作為數組並將它們傳遞給我們的ArrayList構造函數:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   Cat[] catsArray = {thomas, behemoth, lionel, fluffy};

   ArrayList<Cat> catsList = new ArrayList<>(Arrays.asList(catsArray));
   System.out.println(catsList);
}
輸出: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] 也可以反方向走: get來自ArrayList對象的數組。我們使用toArray()方法來做到這一點:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();

   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   Cat[] catsArray = cats.toArray(new Cat[0]);

   System.out.println(Arrays.toString(catsArray));
}
注意:我們向toArray()方法 傳遞了一個空數組。這不是錯誤。在ArrayList類中,此方法的實現方式是傳遞一個空數組以提高其性能。請記住這一點以備將來使用(當然,您可以傳遞某個特定大小的數組;這也可以)。哦,關於大小。可以使用size()方法找到列表的當前大小:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   System.out.println(cats.size());
}
重要的是要理解,與數組的長度屬性不同,ArrayList.size()方法返回元素的實際數量,而不是原始容量。畢竟,我們在創建 ArrayList 時沒有指定大小。但是,您可以指定它——ArrayList一個合適的構造函數。但就添加新元素而言,這不會改變其行為:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>(2);// create an ArrayList with an initial capacity of 2


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   System.out.println(cats.size());
}
控制台輸出: 4 我們創建了一個包含 2 個元素的列表,但它會在我們需要時悄悄擴展。另一個考慮是,如果我們最初創建一個非常小的列表,它將不得不更頻繁地擴展,這將使用一些資源。在本課中,我們幾乎沒有涉及從ArrayList中刪除元素的過程。當然,這並不是因為我們忘記了它。我們已將此主題放入您稍後會遇到的單獨課程中:) 為了鞏固您所學的知識,我們建議您觀看我們的 Java 課程中的視頻課程
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION