JavaRush /Blog Java /Random-VI /Lớp ArrayList trong Java

Lớp ArrayList trong Java

Xuất bản trong nhóm
Xin chào! Trong các bài giảng trước, chúng ta đã xem xét chi tiết cấu trúc dữ liệu như một mảng và xem xét các ví dụ phổ biến khi làm việc với chúng. Nhưng cấu trúc dữ liệu này có một số nhược điểm. Câu trả lời cho họ trong Java là sự xuất hiện của ArrayList. Nói một cách đơn giản nhất có thể, ArrayList trong Java là một mảng được “nâng cấp” với rất nhiều tính năng mới.Lớp ArrayList - 1

Java Arraylist khác với mảng thông thường như thế nào?

Nói chung, mảng khá tiện lợi và như bạn đã nhận thấy, bạn có thể làm rất nhiều thứ với chúng :) Tuy nhiên, mảng cũng có một số nhược điểm.
  • Kích thước hạn chế. Bạn cần biết ở giai đoạn tạo một mảng có bao nhiêu ô. Nếu bạn đánh giá thấp số lượng cần thiết, sẽ không có đủ dung lượng. Nếu bạn đánh giá quá cao, mảng sẽ vẫn trống một nửa và điều đó không quá tệ. Rốt cuộc, hóa ra bạn cũng sẽ phân bổ nhiều bộ nhớ hơn mức cần thiết cho nó.
  • Mảng không có phương thức để thêm phần tử. Bạn luôn phải chỉ định rõ ràng chỉ mục của ô nơi bạn muốn thêm phần tử. Nếu bạn vô tình chỉ định một ô đã bị chiếm giữ với một số giá trị mong muốn, nó sẽ bị ghi đè.
  • Không có phương pháp nào để loại bỏ một phần tử. Giá trị chỉ có thể là “zero”.
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("Hippopotamus");
       cats[2] = new Cat("Philip Markovich");

       cats[1] = null;



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

   @Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
Phần kết luận:

[Cat{name='Томас'}, null, Cat{name='Фorпп Маркович'}]
Tất cả những thiếu sót này có thể được loại bỏ bằng cách sử dụng ArrayList. Nó được tạo ra rất đơn giản:
ArrayList<Cat> cats = new ArrayList<Cat>();
Bây giờ chúng ta đã tạo xong một danh sách để lưu trữ các đối tượng Cat. Chú ý:chúng tôi không chỉ định kích thước của ArrayList vì nó có thể tự động mở rộng. Sao có thể như thế được? Một cách dễ dàng. Bạn sẽ ngạc nhiên, nhưng ArrayList dựa trên một mảng thông thường :) Vâng, bên trong nó có một mảng trong đó các phần tử của chúng ta được lưu trữ. Nhưng ArrayList có một cơ chế đặc biệt để làm việc với nó:
  • Khi mảng bên trong này đầy, ArrayList sẽ tạo một mảng mới bên trong chính nó. Kích thước của nó = (kích thước của mảng cũ * 1,5) +1.
  • Tất cả dữ liệu được sao chép từ mảng cũ sang mảng mới
  • Mảng cũ được bộ thu gom rác loại bỏ.
Nhờ cơ chế này, một ArrayList (ngược lại với một mảng) thực hiện một phương thức để thêm một phần tử mới. Đây là một phương pháp add().
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<Cat>();
   cats.add(new Cat("Hippopotamus"));
}
Phần tử mới được thêm vào cuối danh sách. Bây giờ không còn nguy cơ tràn nên cơ chế này hoàn toàn an toàn. Nhân tiện, ArrayList không chỉ có thể tìm kiếm một đối tượng theo chỉ mục mà còn ngược lại - nó có thể tìm thấy chỉ mục của một đối tượng trong ArrayList bằng cách tham chiếu đến đối tượng đó! Để làm điều này, nó triển khai phương thức indexOf(): Chúng ta chuyển vào nó một liên kết đến đối tượng mong muốn và indexOf()nó trả về chỉ mục của nó cho chúng ta:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   int thomasIndex = cats.indexOf(thomas);
   System.out.println(thomasIndex);
}
Phần kết luận:

0
Đúng vậy, đối tượng thomasthực sự được lưu trữ trong ô 0. Mảng không chỉ có nhược điểm mà còn có những ưu điểm chắc chắn. Một trong số đó đang tìm kiếm một phần tử theo chỉ mục. Vì chúng ta trỏ tới một chỉ mục, tức là tới một địa chỉ cụ thể trong bộ nhớ, nên việc tìm kiếm mảng như vậy diễn ra rất nhanh. ArrayList trong Java cũng có thể làm được điều này! Để làm điều này, nó thực hiện một phương thức get():
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   Cat secondCat = cats.get(1);

   System.out.println(secondCat);
}
Phần kết luận:

Cat{name='Бегемот'}
Ngoài ra, bạn có thể dễ dàng tìm hiểu xem ArrayList có chứa một đối tượng cụ thể hay không. Điều này được thực hiện bằng cách sử dụng phương pháp contains():
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   cats.remove(pushok);
   System.out.println(cats.contains(pushok));
}
Phương thức này kiểm tra xem phần tử có được chứa trong mảng bên trong của ArrayList hay không và trả về kết quả ở dạng boolean- truehoặc false. Phần kết luận:

false
Và một điều quan trọng khác về việc chèn. ArrayList cho phép bạn chèn dữ liệu không chỉ vào cuối mảng mà còn vào bất kỳ ô nào theo chỉ mục. Nó có hai phương pháp cho việc này:
  • add(int index, Cat element)
  • set(int index, Cat element)
Đối với cả hai, bạn chuyển chỉ mục của ô mà bạn muốn chèn vào và một liên kết đến chính đối tượng đó. Sự khác biệt là việc dán qua set()sẽ ghi đè giá trị cũ được lưu trong ô. Và việc chèn qua add()lần đầu tiên sẽ dịch chuyển tất cả các phần tử bắt đầu từ [index]đến cuối mảng và thêm đối tượng bạn cần vào ô trống kết quả. Đây là một ví dụ:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

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

   cats.set(0, philipp);//Now we have a list of 2 cats. We add the 3rd via set:

   System.out.println(cats.toString());
}
Phần kết luận:

[[Cat{name='Томас'}, Cat{name='Бегемот'}]
[Cat{name='Фorпп Маркович'}, Cat{name='Бегемот'}]
Chúng ta đã có danh sách 2 con mèo, chúng ta chèn một con khác thông qua phương thức set()vào ô 0. Kết quả là giá trị cũ được lưu trong ô này đã được thay thế bằng giá trị mới.
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

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

   cats.add(0, philipp);//Now we have a list of 2 cats. Add the 3rd via add

   System.out.println(cats.toString());
}
Nhưng nó add()hoạt động khác hẳn. Anh ta dịch chuyển tất cả các phần tử sang bên phải rồi viết giá trị mới vào ô 0. Phần kết luận:

[Cat{name='Томас'}, Cat{name='Бегемот'}]
[Cat{name='Фorпп Маркович'}, Cat{name='Томас'}, Cat{name='Бегемот'}]
Để xóa hoàn toàn danh sách, hãy sử dụng phương pháp clear():
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   cats.clear();

   System.out.println(cats.toString());
}
Phần kết luận:

[]
Tất cả nội dung đã bị xóa khỏi danh sách. Nhân tiện, hãy chú ý: không giống như mảng, trong ArrayList phương thức toString() bị ghi đè và ngay lập tức hiển thị danh sách ở định dạng chuỗi. Trong trường hợp mảng, chúng ta phải sử dụng lớp Arrays cho việc này. Và vì chúng ta đã nhớ Mảng: trong Java, bạn có thể dễ dàng “chuyển đổi” giữa một mảng và ArrayList, nghĩa là chuyển đổi mảng này sang mảng khác. Lớp Arrays có một phương thức cho việc này là Arrays.asList(). Với sự trợ giúp của nó, chúng ta lấy nội dung của mảng dưới dạng danh sách và chuyển nó đến hàm tạo của ArrayList:
public static void main(String[] args) {

   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   Cat[] catsArray = {thomas, behemoth, philipp, pushok};

   ArrayList<Cat> catsList = new ArrayList<>(Arrays.asList(catsArray));
   System.out.println(catsList);
}
Phần kết luận:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
Bạn có thể làm ngược lại - lấy một mảng từ đối tượng ArrayList. Để thực hiện việc này, hãy sử dụng phương thức toArray():
public static void main(String[] args) {

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

   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

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

   System.out.println(Arrays.toString(catsArray));
}
Xin lưu ý: chúng tôi đã chuyển một mảng trống sang phương thức toArray(). Đó không phải là một sai lầm. Bên trong lớp ArrayList, phương thức này được triển khai theo cách truyền một mảng trống sẽ tăng hiệu suất của nó. Hiện tại, chỉ cần ghi nhớ điều này cho tương lai (nhưng bạn cũng có thể chuyển một kích thước cụ thể, nó sẽ hoạt động). Nói về kích thước. Kích thước hiện tại của danh sách có thể được tìm thấy bằng phương pháp size():
public static void main(String[] args) {

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


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   System.out.println(cats.size());
}
Điều quan trọng cần hiểu ở đây là, không giống như lengththuộc tính mảng, phương thức ArrayList.size() trả về chính xác số phần tử chứ không phải dung lượng ban đầu, vì chúng ta không chỉ định nó khi tạo ArrayList. Nhân tiện, nói chung có thể chỉ ra nó. ArrayList có một hàm tạo tương ứng. Nhưng hành vi của nó trong việc thêm các phần tử mới sẽ không thay đổi:
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("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   System.out.println(cats.size());
}
Đầu ra của bảng điều khiển:

4
Chúng tôi đã tạo một danh sách có 2 thành phần, nhưng khi chúng tôi cần, nó dễ dàng mở rộng. Một điều nữa là nếu ban đầu chúng ta tạo một danh sách rất nhỏ thì nó sẽ phải thực hiện thao tác mở rộng thường xuyên hơn và điều này tiêu tốn một lượng tài nguyên nhất định. Trong bài giảng này, chúng ta hầu như không đề cập đến quá trình loại bỏ các phần tử khỏi ArrayList. Tất nhiên, điều này không phải do quên lãng. Chủ đề này đã được tách thành một bài giảng riêng, bạn có thể đọc thêm :)
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION