JavaRush /Blog Java /Random-VI /Phân tích chi tiết lớp ArrayList [Phần 1]
Vonorim
Mức độ

Phân tích chi tiết lớp ArrayList [Phần 1]

Xuất bản trong nhóm
Bài viết này sẽ xem xét chi tiết về lớp ArrayList từ Khung công tác Bộ sưu tập, đây có lẽ là lớp dễ hiểu nhất do thực tế là nó dựa trên một mảng thông thường. Gần như chắc chắn bạn sẽ được hỏi một câu hỏi về lớp này và cách triển khai nó bằng Java tại cuộc phỏng vấn. Trong phần thứ hai, chúng ta sẽ phân tích các phương thức còn lại và viết cách triển khai mảng động cho các số của riêng chúng ta. Lớp ArrayList kế thừa từ lớp Tóm tắt và triển khai các giao diện sau: List, RandomAccess, Cloneable, Serializable. Phân tích chi tiết về lớp ArrayList [Phần 2] Phân tích chi tiết lớp ArrayList [Phần 1] - 1 Lớp ArrayList hỗ trợ các mảng động có thể mở rộng khi cần thiết. Sự cần thiết và hiệu quả của nó được giải thích bởi thực tế là một mảng thông thường có độ dài cố định: một khi được tạo, nó không thể tăng hoặc giảm, điều này đặt ra các hạn chế nếu không biết mảng đó sẽ lớn đến mức nào. Về cơ bản, lớp ArrayList là một mảng danh sách các tham chiếu đối tượng có độ dài thay đổi. Điều quan trọng là phải hiểu rằng kích thước (số lượng ô) của mảng bên trong không tự động giảm khi các phần tử bị xóa khỏi nó. Trong thực tế, giá trị của biến size, biểu thị số phần tử thực sự có trong mảng, bị giảm. Giả sử chúng ta tạo một đối tượng mới của lớp ArrayList và thêm 5 phần tử vào đó. Theo mặc định, một mảng gồm 10 phần tử được tạo. Trong trường hợp này, cái gọi là dung lượng (kích thước/khối lượng) của đối tượng của chúng ta sẽ bằng 10, nhưng giá trị của biến sizesẽ bằng 5. Và khi chúng ta xóa các phần tử, chúng ta sẽ thấy những thay đổi về giá trị của biến size, vì chúng ta .lengthkhông thể truy cập vào mảng bên trong của lớp ArrayList và tìm ra độ dài của nó. Kích thước có thể được giảm bằng cách sử dụng một phương pháp bổ sung trimToSize(), sẽ được thảo luận bên dưới. Chúng ta hãy nhìn vào các trường lớp.
  • Trường chịu trách nhiệm về âm lượng mặc định của mảng động:

    private static final int DEFAULT_CAPACITY = 10

    Khi tạo một đối tượng mới new ArrayList<>() (hàm tạo không có tham số), một mảng gồm 10 phần tử được tạo bên trong.

  • Trường trong đó tất cả các thành phần của bộ sưu tập được lưu trữ:

    transient Object[] elementData

    Được đánh dấu bằng từ khóa transient- trường không được ghi vào luồng byte khi sử dụng thuật toán tuần tự hóa tiêu chuẩn. Điều đáng chú ý là trường này không được đánh dấu bằng từ khóa private, nhưng điều này được thực hiện để tạo điều kiện truy cập vào trường này từ các lớp lồng nhau (ví dụ: Danh sách con).

  • Trường bộ đếm lưu trữ số phần tử thực sự có trong mảng:

    private int size

    Giá trị được tăng/giảm khi thực hiện các thao tác như chèn và xóa.

Có thêm 3 trường nữa trong lớp, nhưng về cơ bản chúng là những trường bổ sung nên không có ích gì khi xem xét chúng. Lớp này có ba hàm tạo:
  1. public ArrayList()– tạo một mảng danh sách trống gồm 10 phần tử;
  2. public ArrayList(Collection < ? extends E > c)– tạo một mảng danh sách được khởi tạo với các phần tử từ bộ sưu tập đã truyền (nếu chúng ta muốn tạo một ArrayList mới dựa trên một số bộ sưu tập);
  3. public ArrayList(int initialCapacity)– tạo một mảng danh sách với dung lượng ban đầu. Nếu tham số initCapacity được truyền lớn hơn 0 thì một mảng có kích thước đã chỉ định sẽ được tạo (trường nội bộ elementData được gán một liên kết đến một mảng mới thuộc loại Đối tượng có kích thước initCapacity). Nếu tham số là 0 thì một mảng trống sẽ được tạo. Nếu tham số được chỉ định nhỏ hơn 0 thì IllegalArgumentException sẽ được ném ra.
Tạo một đối tượng
List < String> list = new ArrayList<>();
Đối tượng mới được tạo listchứa các thuộc tính (trường) elementDatasize. Kho lưu trữ giá trị elementDatakhông gì khác hơn là một mảng thuộc một loại cụ thể (được chỉ định chung – <>), trong trường hợp của chúng tôi String[]là . Nếu một hàm tạo không có tham số được gọi thì theo mặc định, một mảng gồm 10 phần tử thuộc loại Object sẽ được tạo (tất nhiên là có kiểu truyền tới kiểu đó). Phân tích chi tiết lớp ArrayList [Phần 1] - 2Thêm phần tử Việc thêm phần tử vào một mảng danh sách theo cách cổ điển được thực hiện bằng cách sử dụng các biến thể quá tải của add().
public boolean add(E элемент)
Chà, hãy thêm: list.add("0"); Phân tích chi tiết lớp ArrayList [Phần 1] - 3Bên trong phương thức này, một phiên bản quá tải của phương thức được add()gọi, được đánh dấu là private, lần lượt lấy ba tham số làm đầu vào: phần tử được thêm vào, mảng bên trong và kích thước của nó. Trong phương thức riêng tư, quá trình kiểm tra xảy ra: nếu tham số kích thước được truyền bằng với độ dài của mảng bên trong (nghĩa là mảng đã đầy), thì mảng được gán kết quả của phương thức grow(int minCapacity)(giá trị hiện tại của trường size + 1 được truyền cho phương thức, vì cần phải tính đến phần tử được thêm vào), trong đó bên trong mảng được gán một liên kết đến mảng mới được tạo bằng cách sao chép các phần tử của mảng ban đầu:
Arrays.copyOf(elementData, newCapacity(minCapacity))
Là tham số thứ hai của phương thức, copyOfchúng tôi chỉ ra kết quả của phương thức newCapacity(int minCapacity), trong đó kích thước mảng mới được tính toán. Nó được tính bằng công thức sau: int newCapacity = oldCapacity + (oldCapacity >> 1) Đối với một mảng có kích thước mặc định, điều sau đây sẽ đúng: >> 1– dịch chuyển bit sang phải một đơn vị (toán tử giảm một số xuống một nửa số đó). Về cơ bản, nó có nghĩa là chia cho 2 lũy thừa 1. Hóa ra là chúng ta chia 10 cho 2 và cộng 10. Tổng cộng, dung lượng mới của mảng là 15, nhưng vì chúng ta đang thêm phần tử thứ 11 nên 15 + 1 = 16. Hãy quay lại danh sách của chúng ta và giả sử rằng chúng ta đã thêm 10 phần tử vào đó và thử thêm 11. Việc kiểm tra sẽ cho thấy rằng không có khoảng trống trong mảng. Theo đó, một mảng mới được tạo và gọi Arrays.copyOf, mảng này sử dụng phương thức hệ thống bên trong System.arraycopy(). Phân tích chi tiết lớp ArrayList [Phần 1] - 4Phân tích chi tiết lớp ArrayList [Phần 1] - 5Hoặc đây là một ví dụ rõ ràng từ một bài viết trên JavaRush: Phân tích chi tiết lớp ArrayList [Phần 1] - 6Sau tất cả những lần kiểm tra này và tăng kích thước của mảng nếu cần, thì trong một phương thức riêng tư, add()một phần tử mới sẽ được thêm vào cuối mảng và tham số hiện tại sizesẽ tăng thêm một . Mảng cũ sau đó sẽ được xử lý bởi trình thu gom rác. Đây là cách hoạt động của mảng động: khi thêm các phần tử, chúng tôi kiểm tra xem còn chỗ trống trong đó hay không. Nếu có khoảng trống thì chúng ta chỉ cần thêm phần tử vào cuối mảng. Kết thúc không có nghĩa là ô cuối cùng trong mảng mà là ô tương ứng với giá trị size. Chúng ta đã thêm phần tử đầu tiên vào mảng; nó được đặt trong ô có chỉ mục [0]. Giá trị trường sizeđã tăng thêm một và = 1. Chúng ta thêm phần tử tiếp theo: chúng ta thấy rằng size = 1, theo đó chúng ta đặt phần tử vào ô có chỉ mục [1], v.v. Có một phiên bản quá tải của phương thức này với hai tham số:
public void add(int index, E element)
Chúng ta có thể chỉ định vị trí (chỉ mục) của ô nơi chúng ta muốn thêm phần tử. Đầu tiên, tính chính xác của giá trị chỉ mục đã chỉ định sẽ được kiểm tra, vì có khả năng chỉ mục không chính xác sẽ được chỉ định, điều này sẽ trỏ đến một ô không có gì hoặc đơn giản là không tồn tại. Kiểm tra chỉ mục: index > size || index < 0– nếu chỉ mục được chỉ định lớn hơn kích thước hiện tại của mảng hoặc nhỏ hơn 0 thì sẽ đưa ra một ngoại lệ IndexOutOfBoundsException. Sau đó, nếu cần, kích thước của mảng sẽ được tăng lên, tương tự như ví dụ trên. Bạn có thể đã nghe nói rằng trong các thao tác thêm/xóa trong một mảng, một cái gì đó sẽ được dịch chuyển ở đâu đó (sang phải hoặc sang trái). Vì vậy, việc dịch chuyển được thực hiện bằng cách sao chép mảng: System.arraycopy(elementData, index, elementData, index + 1, s - index); Tất cả các phần tử nằm ở bên phải của chỉ mục đã chỉ định sẽ được dịch chuyển sang phải một vị trí (index+1). Và chỉ sau đó một phần tử mới mới được thêm vào mảng bên trong tại chỉ mục đã chỉ định. Vì chúng ta đã dịch chuyển một phần của mảng sang bên phải (một mảng mới không được tạo), nên ô chúng ta cần sẽ được tự do để ghi. Liên kết đến mảng cũ sẽ bị xóa và trong tương lai nó sẽ bị người thu gom rác tiếp quản. Dán "maserati" vào ô [3] đã bị chiếm:
Phân tích chi tiết lớp ArrayList [Phần 1] - 7
Do đó, khi một phần tử được chèn vào chỉ mục và không có khoảng trống trong mảng, lệnh gọi System.arraycopy()sẽ xảy ra hai lần: lần đầu tiên in grow(), lần thứ hai trong chính phương thức đó add(index, value), điều này sẽ ảnh hưởng rõ ràng đến tốc độ của toàn bộ thao tác thêm. Kết quả là, khi cần ghi một phần tử khác vào mảng bên trong nhưng không còn khoảng trống ở đó, thì đây là điều sẽ xảy ra bên trong ArrayList:
  • Một mảng mới được tạo với kích thước lớn hơn 1,5 lần so với mảng ban đầu, cộng thêm một phần tử.
  • Tất cả các phần tử từ mảng cũ được sao chép sang mảng mới
  • Mảng mới được lưu trữ trong biến nội bộ của đối tượng ArrayList và mảng cũ được khai báo là rác.
Dung lượng của các đối tượng thuộc loại ArrayList có thể được tăng lên theo cách thủ công bằng phương thức:
public void ensureCapacity(int minCapacity)
Bằng cách tăng trước dung lượng mảng, bạn có thể tránh được việc phân phối lại RAM sau này. Phương thức này tăng kích thước của mảng bên trong để chứa số phần tử được truyền vào minCapacity. Phương thức này ensureCapacity()không ảnh hưởng đến trường size, nó ảnh hưởng đến capacity(kích thước của) mảng bên trong. Một lần nữa tôi nhấn mạnh rằng sizecả hai đều là capacitynhững thứ khác nhau và điều rất quan trọng là đừng nhầm lẫn chúng! Nếu bạn muốn giảm kích thước của mảng cơ bản mà từ đó ArrayList được xây dựng xuống số phần tử hiện tại được lưu trữ thực sự, bạn nên gọi phương thức trimToSize(). Sau khi xóa các phần tử khỏi bộ sưu tập, size()nó sẽ hiển thị số lượng phần tử thực sự tồn tại và capacitysẽ không giảm! Giả sử: chúng ta nhập 100 phần tử, xóa 50 phần tử đầu tiên, sizenó sẽ bằng 50 và capacitygiữ nguyên là 100. Để giảm và capacity, chúng ta cần sử dụng phương thức trimToSize(), điều chỉnh toàn bộ dung lượng của chúng ta theo kích thước hiện tại. Làm thế nào nó phù hợp? Sao chép mảng của chúng tôi để không còn ô trống (độ dài của mảng mới chỉ bằng trường kích thước).
Phân tích chi tiết lớp ArrayList [Phần 1] - 8
Bạn cũng có thể thêm các phần tử vào bộ sưu tập của chúng tôi bằng cách sử dụng tệp addAll.
public boolean addAll(Collection< ? extends E> c)
public boolean addAll(int index, Collection< ? extends E> collection);
Tùy chọn đầu tiên cho phép bạn thêm tất cả các thành phần từ bộ sưu tập được chỉ định trong tham số phương thức (ví dụ: một trang tính khác) vào bộ sưu tập gốc (chèn vào cuối) mà lệnh gọi phương thức đã được thực hiện. Bộ sưu tập đã truyền (cũng có thể là một tập hợp) được chuyển đổi thành một mảng bằng cách sử dụng phương thức toArray(). Đương nhiên, thao tác thêm cũng được thực hiện bằng cách sao chép. Cách thứ hai là thêm tất cả các phần tử collectionvào danh sách, bắt đầu từ chỉ mục index. Trong trường hợp này, tất cả các phần tử sẽ dịch chuyển sang phải theo số phần tử trong danh sách collection. Loại bỏ các phần tử Trước tiên, hãy xem xét các tùy chọn cổ điển để loại bỏ các phần tử khỏi ArrayList.
public E remove(int index)
Thực hiện xóa theo chỉ mục và dịch chuyển tất cả các phần tử tiếp theo (sau phần tử tại chỉ mục đã chỉ định) sang trái, từ đó đóng các “lỗ hổng”. Nó cũng trả về phần tử đã xóa (E), phần tử này trước đó được ghi vào một biến bổ sung trước khi xóa, giá trị mà chúng ta nhận được do lệnh gọi phương thức. Để hiểu E là gì, bạn sẽ cần phải làm quen với cái gọi là các loại chung. Ký hiệu E chỉ ra rằng phương thức trả về kiểu dữ liệu đã được chỉ định khi tạo đối tượng ArrayList (hãy nhớ: List <String> list, tương ứng, trong trường hợp này, E sẽ được “thay thế” String). Để hiểu tổng quát, tôi thực sự khuyên bạn nên tự làm quen với các loại chung. Tính chính xác của chỉ mục đã nhập được kiểm tra, sau đó bên trong phương thức, phần tử không bị xóa hoàn toàn mà một phương thức riêng tư được gọi fastRemove(Object[] es, int i), trong đó việc xóa đã xảy ra. Chúng tôi chuyển mảng của mình và chỉ mục đã chỉ định cho phương thức làm đầu vào. Các phần tử được sao chép bằng cách sử dụng System.arraycopy(), kích thước của mảng được giảm xuống và sau đó chúng tôi gán null cho phần tử cuối cùng. Điều đáng chú ý là một mảng mới không được tạo: System.arraycopy(es, i + 1, es, i, size - 1 - i); Phần ở bên phải của vị trí theo chỉ mục đã chỉ định (i+1) được sao chép vào (các) mảng ban đầu của chúng tôi và nó được đặt bắt đầu từ chính vị trí đó. (i) vị trí của phần tử cần xóa. Vì vậy, chúng tôi đã thực hiện dịch chuyển sang trái và xóa phần tử của mình.
Phân tích chi tiết lớp ArrayList [Phần 1] - 9
Hãy thử xóa phần tử ở chỉ mục 3 khỏi mảng bên dưới:
Phân tích chi tiết lớp ArrayList [Phần 1] - 10
Hãy xem xét phiên bản thứ hai của phương pháp:
public boolean remove(Object o)
Phương thức này loại bỏ phần tử được truyền khỏi danh sách o, hay chính xác hơn là đối tượng tại liên kết đã chỉ định. Nếu một phần tử có trong danh sách, nó sẽ bị xóa và tất cả các phần tử sẽ được dịch sang trái. Nếu phần tử tồn tại trong danh sách và được xóa thành công, phương thức trả về true; nếu không thì trả về false. Tương tự như tùy chọn xóa theo chỉ mục, phương thức này được gọi fastRemove(), trong đó các hành động tương tự xảy ra. Sự khác biệt là phương thức này remove(Object o)còn tìm kiếm thêm đối tượng mong muốn thông qua một phương thức equals()của lớp Object. Khi loại bỏ theo giá trị, vòng lặp sẽ đi qua tất cả các phần tử của danh sách cho đến khi tìm thấy kết quả khớp. Chỉ phần tử đầu tiên được tìm thấy sẽ bị xóa. Tóm lại: khi xóa các phần tử khỏi mảng động, không còn lỗ trống như trong mảng thông thường (ô bị xóa sẽ không trống). Tất cả các phần tử tiếp theo (ở bên phải của chỉ mục) được dịch chuyển sang trái một vị trí. Có một số phương pháp bổ sung có thể được sử dụng để xóa các thành phần khỏi danh sách ở các mức độ khác nhau. Chúng ta hãy nhìn vào chúng một cách ngắn gọn. Làm sạch bộ sưu tập của chúng tôi:
public void clear()
Một vòng lặp đơn giản forlặp qua tất cả các phần tử của một mảng, gán giá trị null cho mỗi phần tử. Bạn có thể xóa các thành phần đó khỏi bộ sưu tập của chúng tôi có trong một bộ sưu tập được chuyển khác như thế này:
public boolean removeAll(Collection< ?> c)
Nếu bạn cần loại bỏ một số phần tử, có lẽ bạn không nên thực hiện việc đó trong vòng lặp có điều kiện: sử dụng phương thức này sẽ thuận tiện và an toàn hơn removeAll(). Nó chấp nhận một tập hợp các phần tử sẽ bị xóa khỏi danh sách. Bộ sưu tập phải chứa các phần tử cùng loại mà danh sách đích lưu trữ. Nếu không nó sẽ bị vứt đi ClassCastException. Phương thức sẽ trả về true nếu danh sách bị thay đổi do lệnh gọi phương thức.
Phân tích chi tiết lớp ArrayList [Phần 1] - 11
Xóa các phần tử không thuộc bộ sưu tập đã truyền:
public boolean retainAll(Collection< ?> c)
Phân tích chi tiết lớp ArrayList [Phần 1] - 12
Giả sử chúng ta có một bộ sưu tập:
List< String> listFirst = new ArrayList<>();
listFirst.add("White");
listFirst.add("Black");
listFirst.add("Red");
Va thu hai:
List< String> listSecond = new ArrayList<>();
listSecond.add("Green");
listSecond.add("Red");
listSecond.add("White");
Sau đó listSecond.retainAll(listFirst)vào listSecondsẽ vẫn còn:

"White"
"Red"
Vì "Green" đã bị xóa nên không có trong listFirst. Nhưng sau listSecond.removeAll(listFirst)đó nó listSecondsẽ vẫn còn:

"Green"
Удалorсь все элементы, которые есть в listFirst.
Không thuộc bộ sưu tập đã truyền - có nghĩa là nếu có các phần tử không có trong bộ sưu tập đã truyền, thì bạn cần xóa chúng khỏi bộ sưu tập đầu tiên (phương thức được áp dụng). Thuộc bộ sưu tập đã chuyển - theo đó, nếu có một phần tử trong cả bộ sưu tập thứ nhất và thứ hai (đã chuyển), thì bản sao từ bộ sưu tập đầu tiên sẽ bị hủy.
protected void removeRange(int fromIndex, int toIndex)
Xóa khỏi danh sách tất cả các phần tử nằm giữa chỉ mục được chỉ định bắt đầu (đã bao gồm) và chỉ mục được chỉ định kết thúc (không bao gồm). Điều đáng lưu ý là phương thức này không thể được gọi trực tiếp trên đối tượng ArrayList. Để sử dụng nó, bạn cần kế thừa từ AbstractList/ArrayList. Phương thức này cũng được sử dụng bởi một phương thức khác (SubList, sẽ được thảo luận sau).
public boolean removeIf(Predicate< ? super E> filter)
Xóa các phần tử khỏi bộ sưu tập dựa trên một vị từ nhất định. Bản thân vị từ là một hàm/thuật toán/điều kiện nhất định, trên cơ sở đó một hoặc nhiều phần tử tương ứng với một điều kiện nhất định sẽ bị loại bỏ. Predicate— một giao diện chức năng (chỉ chứa một phương thức nên có thể được sử dụng như lambda), hoạt động theo nguyên tắc “nhận một tham số - trả về boolean”. Về cơ bản, phương thức này sẽ ghi đè quá trình triển khai từ giao diện Collectionvà triển khai "chiến lược" sau: nó lặp qua các phần tử và đánh dấu những phần tử khớp với Predicate; sau đó nó được chạy qua lần thứ hai để loại bỏ (và dịch chuyển) các phần tử đã được đánh dấu trong lần lặp đầu tiên. Hãy triển khai một giao diện Predicatesẽ trả về true nếu hai đối tượng bằng nhau:
class SamplePredicate< T> implements Predicate< T>{
  T varc1;
  public boolean test(T varc){
     if(varc1.equals(varc)){
       return true;
  }
  return false;
  }
}
Trong một lớp khác, hãy tạo một ArrayList từ Stringvà một đối tượng của lớp chúng ta thực hiện Predicate:
ArrayList< String> color_list = new ArrayList<> ();
SamplePredicate< String> filter = new SamplePredicate<> ();
varc1Hãy viết giá trị "Trắng" vào biến :
filter.varc1 = "White";
Hãy thêm một vài dòng vào danh sách:
color_list.add("White");
color_list.add("Black");
color_list.add("Red");
color_list.add("White");
color_list.add("Yellow");
color_list.add("White");
Hãy thực thi phương thức trên list removeIf, mà chúng ta sẽ chuyển đối tượng của mình với điều kiện:
color_list.removeIf(filter);
Kết quả là tất cả các hàng có giá trị "Trắng" sẽ bị xóa khỏi danh sách vì "vị ngữ" của chúng tôi so sánh chúng về sự bằng nhau. Danh sách cuối cùng: [Đen, Đỏ, Vàng].
Phân tích chi tiết lớp ArrayList [Phần 1] - 13
Thay thế các phần tử
public E set(int index, E element)
Thay thế phần tử tại vị trí đã chỉ định indexbằng phần tử đã được truyền element. Chỉ số này cũng phải lớn hơn 0 và nhỏ hơn chỉ số của phần tử cuối cùng, nếu không sẽ có ngoại lệ IndexOutOfBoundsException. Không có bản sao của mảng nội bộ xảy ra. Đơn giản, thay vì phần tử ở chỉ mục đã chỉ định, một phần tử mới sẽ được chèn vào, tức là. ghi đè giá trị.
Phân tích chi tiết lớp ArrayList [Phần 1] - 14
public void replaceAll(UnaryOperator<e> operator)
Thay đổi tất cả các thành phần của bộ sưu tập (có thể kèm theo một điều kiện). Chủ yếu được sử dụng kết hợp với lambdas hoặc một lớp ẩn danh (nhưng để rõ ràng, trong ví dụ này chúng ta sẽ chỉ sử dụng một lớp triển khai giao diện) để triển khai giao diện UnaryOperatorvà xác định các phương thức của nó. Hãy thực hiện giao diện:
class MyOperator< T> implements UnaryOperator< T>{
   T varc1;
   public T apply(T varc){
     return varc1;
  }
}
Trong một lớp khác, hãy tạo một ArrayList từ Stringvà một đối tượng của lớp chúng ta thực hiện UnaryOperator:
ArrayList< String> color_list = new ArrayList<> ();
MyOperator< String> operator = new MyOperator<> ();
varc1Hãy viết giá trị "Trắng" vào biến :
operator.varc1 = "White";
Hãy thêm một vài dòng vào danh sách:
color_list.add("White");
color_list.add("Black");
color_list.add("Red");
color_list.add("White");
color_list.add("Yellow");
color_list.add("White");
Hãy thực thi một phương thức trong danh sách replaceAllmà chúng ta sẽ chuyển đối tượng của mình tới operator:
color_list.replaceAll(operator);
Kết quả là tất cả các giá trị trong danh sách được thay thế bằng "Trắng": [Trắng, Trắng, Trắng, Trắng, Trắng, Trắng]. Và đây là cách, ví dụ: bạn có thể xóa tất cả khoảng trắng khỏi các chuỗi có trong bộ sưu tập:
ArrayList< String> list = new ArrayList<>(Arrays.asList("A   ", "  B  ", "C"));
list.replaceAll(String::trim);
Các phương pháp khác: Bạn có thể chuyển đổi mảng danh sách ArrayList thành mảng thông thường bằng phương thức:
public Object[] toArray()
hoặc
public < T> T[] toArray(T[] a)
- ở đây kiểu của mảng trả về được xác định trong runtime Phương thức này sẽ cho phép:
  1. tăng tốc một số thao tác;
  2. truyền một mảng dưới dạng tham số cho một phương thức không bị quá tải để chấp nhận trực tiếp bộ sưu tập;
  3. Tích hợp mã dựa trên bộ sưu tập mới với mã kế thừa không nhận dạng bộ sưu tập.
Trả về một đối tượng sao chép của mảng:
public Object clone()
Xin lưu ý rằng phương thức clone()trả về kiểu Đối tượng, vì vậy sau khi gọi nó, bạn sẽ cần chuyển sang lớp được yêu cầu. Nhân bản tạo ra một đối tượng độc lập mới. Kiểm tra bộ sưu tập xem có sự hiện diện của một đối tượng không:
public boolean contains(Object o)
Kiểm tra sự hiện diện của một đối tượng trong danh sách (sử dụng nội bộ phương thức bằng của lớp Object, tức là so sánh các tham chiếu), trả về đúng/sai tùy thuộc vào kết quả. Ngoài các vòng lặp thông thường, bạn có thể lặp qua (truy cập từng phần tử cũng như thực hiện một số hành động) một bộ sưu tập bằng cách sử dụng:
public void forEach(Consumer< ? super E> action)
Đây là cách chúng tôi có thể hiển thị danh sách của mình:
List< Integer> numbers = new ArrayList<>(Arrays.asList(10, 20, 50, 100, -5));
numbers.forEach((number)-> System.out.println(number));
Nếu không sử dụng lambdas, bạn cần sử dụng một lớp ẩn danh và ghi đè phương thức acceptgiao diện Consumer:
numbers.forEach(new Consumer< Integer>() {
  @Override
   public void accept(Integer integer) {
      System.out.println(integer);
          }
});
Lấy một phần tử theo chỉ mục của nó:
public E get(int index)
Được sử dụng để truy cập ngẫu nhiên vào các phần tử bộ sưu tập. Trả về phần tử nằm trong danh sách tại chỉ mục đã chỉ định. Nếu index < 0hoặc là index >=số phần tử tối đa trong danh sách, một ngoại lệ sẽ được đưa ra IndexOutOfBoundsException. Đây là phương pháp cơ bản để truy xuất một phần tử từ danh sách và thời gian truy xuất một phần tử theo chỉ mục sẽ luôn giống nhau, bất kể kích thước của ArrayList vì nó đang truy cập vào một ô mảng cụ thể. Tìm chỉ mục cho các đối tượng được chỉ định:
public int indexOf(Object o);
public int lastIndexOf(Object o);
Các phương thức trả về chỉ mục của phần tử đầu tiên (khi đối tượng đã cho gặp lần đầu) hoặc lần xuất hiện cuối cùng (khi đối tượng đã cho gặp lần cuối) trong danh sách. Nếu phần tử không tồn tại trong danh sách, các phương thức sẽ trả về -1.
Phân tích chi tiết lớp ArrayList [Phần 1] - 16
Phân tích chi tiết lớp ArrayList [Phần 1] - 17
Kiểm tra bộ sưu tập để tìm các phần tử:
public boolean isEmpty();
Phương thức trả về true nếu danh sách trống (xem liệu trường có bằng nhau không size 0), nếu không thì trả về false. Nếu danh sách chỉ chứa các phần tử null thì phương thức sẽ trả về false. Nói cách khác, các phần tử null cũng được tính đến bằng phương pháp này. Tìm số phần tử trong một danh sách:
public int size();
Trả về số phần tử trong danh sách (giá trị trường kích thước). Số lượng phần tử có thể khác với dung lượng (dung lượng) của danh sách. Nhận một trình vòng lặp cho một danh sách:
public Iterator< E> iterator();
Trả về một trình vòng lặp cho một danh sách để sử dụng sau này trong một vòng lặp hoặc bất kỳ quá trình xử lý nào khác. Trình vòng lặp thực hiện hành vi không nhanh. Nếu nó chạy qua bộ sưu tập và nhận thấy một số sửa đổi đối với nó (không thu được bằng các phương thức lặp), thì nó sẽ ngay lập tức đưa ra một ngoại lệ ConcurrentModificationException. Trình vòng lặp có một thứ gọi là modification count. Khi trình lặp lặp qua bộ sưu tập sau mỗi next/hasNext/remove, nó sẽ kiểm tra bộ đếm này. Nếu nó không khớp với những gì iterator mong đợi sẽ thấy, nó sẽ đưa ra một ngoại lệ. Tôi sẽ không xem xét chi tiết các vòng lặp ở đây.
public ListIterator< E> listIterator() и public ListIterator< E> listIterator(int index)
Trả về một trình vòng lặp danh sách cho một danh sách để sử dụng sau này trong một vòng lặp hoặc bất kỳ quá trình xử lý nào khác. Giao diện ListIteratormở rộng giao diện Iteratorđể duyệt qua danh sách hai chiều và sửa đổi các thành phần của nó. Trong phiên bản quá tải, bạn có thể chuyển chỉ mục mà từ đó quá trình “truyền tải” sẽ bắt đầu. Chỉ mục trong trường hợp này biểu thị phần tử đầu tiên mà phương thức sẽ bắt đầu công việc của nó next()và khi phương thức được gọi, previous()quá trình truyền tải sẽ bắt đầu từ phần tử bên dưới chỉ mục “chỉ mục đã qua - 1”.
public Spliterator <E> spliterator()
Java 8 giới thiệu một loại trình vòng lặp liên kết trễ và vòng lặp không nhanh mới được gọi là trình vòng lặp dấu phân cách. Các trình vòng lặp phân cách cho phép bạn lặp lại một chuỗi các phần tử, nhưng chúng được sử dụng theo một cách khác. Tính năng quan trọng nhất của giao diện Spliterator là khả năng hỗ trợ lặp lại song song các phần riêng lẻ của một chuỗi các phần tử và do đó lập trình song song.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION