Java ArrayList làm thế nào để thêm các phần tử lúc đầu


183

Tôi cần thêm các phần tử vào ArrayListhàng đợi bất cứ điều gì, nhưng khi tôi gọi hàm để thêm một phần tử, tôi muốn nó thêm phần tử vào đầu mảng (để nó có chỉ mục thấp nhất) và nếu mảng có thêm 10 phần tử một kết quả mới trong việc xóa phần tử cũ nhất (phần tử có chỉ số cao nhất).

Có ai có bất cứ đề nghị?


Bạn có nghĩa là thích removeadd?
Peter Lawrey

Bạn đang sử dụng cái gì arraylist stack queue whateverđể thêm vào đầu một mảng là tốt nhất nên tránh và có vẻ như bạn nên sử dụng một bộ sưu tập khác.
Peter Lawrey

Đầu tiên, bạn nên tự làm một cái gì đó. Anh đã làm gì cho đến nay?
Yegoshin Maxim

Câu trả lời:


301

Listcó phương pháp add(int, E), vì vậy bạn có thể sử dụng:

list.add(0, yourObject);

Sau đó, bạn có thể xóa phần tử cuối cùng với:

if(list.size() > 10)
    list.remove(list.size() - 1);

Tuy nhiên, bạn có thể muốn xem xét lại các yêu cầu của mình hoặc sử dụng cấu trúc dữ liệu khác, như Queue

BIÊN TẬP

Có thể có một cái nhìn về Apache CircularFifoQueue:

CircularFifoQueue là hàng đợi vào trước xuất trước với kích thước cố định thay thế phần tử cũ nhất của nó nếu đầy.

Chỉ cần khởi tạo nó với kích thước tối đa của bạn:

CircularFifoQueue queue = new CircularFifoQueue(10);

10
Tôi sẽ không chạm vào bất kỳ thư viện apache nào với cột điện mười feet, đặc biệt là khi các lớp sưu tập của ổi tồn tại. EvictingQueue của Guava có thể là một lựa chọn tốt ở đây.
DPM

26

Sử dụng dữ liệu cụ thể

Có nhiều cấu trúc dữ liệu khác nhau được tối ưu hóa để thêm các yếu tố ở chỉ mục đầu tiên. Mặc dù vậy, nếu bạn chuyển đổi bộ sưu tập của mình thành một trong số đó, cuộc trò chuyện có thể sẽ cần sự phức tạp về thời gian và không gian củaO(n)

Deque

JDK bao gồm Dequecấu trúc cung cấp các phương thức như addFirst(e)offerFirst(e)

Deque<String> deque = new LinkedList<>();
deque.add("two");
deque.add("one");
deque.addFirst("three");
//prints "three", "two", "one"

Phân tích

Độ phức tạp không gian và thời gian của chèn là với LinkedListhằng số ( O(1)). Xem áo choàng của Big-O .

Đảo ngược danh sách

Một phương pháp rất dễ dàng nhưng không hiệu quả là sử dụng ngược lại:

 Collections.reverse(list);
 list.add(elementForTop);
 Collections.reverse(list);

Nếu bạn sử dụng luồng Java 8, câu trả lời này có thể khiến bạn quan tâm.

Phân tích

  • Độ phức tạp thời gian: O(n)
  • Độ phức tạp không gian: O(1)

Nhìn vào việc triển khai JDK, điều này có O(n)độ phức tạp về thời gian nên chỉ phù hợp với các danh sách rất nhỏ.


Đảo ngược một danh sách hai lần. Nó sẽ thêm thời gian chạy của thuật toán bằng một lề lớn so với giải pháp được chấp nhận ở trên?
Samyak Upadhyay

Nó thêm 2n, vì vậy, nhưng nếu bạn có danh sách <50, bạn sẽ không thể đạt điểm chuẩn vi sai trên hầu hết các máy hiện đại
Patrick Favre

8

Bạn có thể xem phần add (int index, phần tử E) :

Chèn phần tử được chỉ định vào vị trí đã chỉ định trong danh sách này. Chuyển phần tử hiện tại ở vị trí đó (nếu có) và bất kỳ phần tử tiếp theo nào sang bên phải (thêm một phần tử vào chỉ số của chúng).

Khi bạn thêm, bạn có thể kiểm tra kích thước của ArrayList và loại bỏ những cái ở cuối.


4

Bạn có thể muốn nhìn vào Deque. nó cho phép bạn truy cập trực tiếp vào cả hai mục đầu tiên và cuối cùng trong danh sách.


1
Tôi ngạc nhiên khi bạn là câu trả lời duy nhất nói về Deque, đây rõ ràng là giải pháp tối ưu tốt nhất.
Guillaume F.

3

Những gì bạn đang mô tả, là một tình huống thích hợp để sử dụng Queue.

Vì bạn muốn addyếu tố mới, và yếu tố removecũ. Bạn có thể thêm vào cuối và loại bỏ từ đầu. Điều đó sẽ không tạo ra nhiều sự khác biệt.

Hàng đợi có các phương thức add(e)remove()bổ sung vào cuối phần tử mới và loại bỏ phần đầu tương ứng.

Queue<Integer> queue = new LinkedList<Integer>();
queue.add(5);
queue.add(6);
queue.remove();  // Remove 5

Vì vậy, mỗi khi bạn thêm một phần tử vào, queuebạn có thể sao lưu nó bằng một removecuộc gọi phương thức.


CẬP NHẬT : -

Và nếu bạn muốn sửa kích thước củaQueue , thì bạn có thể xem: -ApacheCommons#CircularFifoBuffer

Từ documentation: -

ThongFifoBuffer là bộ đệm đầu tiên xuất hiện với kích thước cố định thay thế phần tử cũ nhất của nó nếu đầy đủ.

Buffer queue = new CircularFifoBuffer(2); // Max size

queue.add(5);
queue.add(6);
queue.add(7);  // Automatically removes the first element `5`

Như bạn có thể thấy, khi đạt đến kích thước tối đa, sau đó thêm phần tử mới sẽ tự động loại bỏ phần tử đầu tiên được chèn.


1

Tôi nghĩ việc triển khai nên dễ dàng, nhưng xem xét về hiệu quả, bạn nên sử dụng LinkedList chứ không phải ArrayList làm container. Bạn có thể tham khảo đoạn mã sau:

import java.util.LinkedList;
import java.util.List;

public class DataContainer {

    private List<Integer> list;

    int length = 10;
    public void addDataToArrayList(int data){
        list.add(0, data);
        if(list.size()>10){
            list.remove(length);
        }
    }

    public static void main(String[] args) {
        DataContainer comp = new DataContainer();
        comp.list = new LinkedList<Integer>();

        int cycleCount = 100000000;

        for(int i = 0; i < cycleCount; i ++){
            comp.addDataToArrayList(i);
        }
    }
}


0

bạn có thể sử dụng mã này

private List myList = new ArrayList();
private void addItemToList(Object obj){
    if(myList.size()<10){
      myList.add(0,obj);
    }else{
      myList.add(0,obj);
      myList.remove(10);
    }
}

0

Bạn có thể sử dụng phương pháp danh sách, loại bỏ và thêm

list.add(lowestIndex, element);
list.remove(highestIndex, element);

0

Lấy ví dụ này: -

List<String> element1 = new ArrayList<>();
element1.add("two");
element1.add("three");
List<String> element2 = new ArrayList<>();
element2.add("one");
element2.addAll(element1);

-1

Bạn có thể dùng

public List<E> addToListStart(List<E> list, E obj){
list.add(0,obj);
return (List<E>)list;

}

Thay đổi E với kiểu dữ liệu của bạn

Nếu xóa phần tử cũ nhất là cần thiết thì bạn có thể thêm:

list.remove(list.size()-1); 

trước khi tuyên bố trở lại. Nếu không, danh sách sẽ thêm đối tượng của bạn lúc đầu và cũng giữ lại phần tử cũ nhất.

Điều này sẽ xóa phần tử cuối cùng trong danh sách.


-1
import java.util.*:
public class Logic {
  List<String> list = new ArrayList<String>();
  public static void main(String...args) {
  Scanner input = new Scanner(System.in);
    Logic obj = new Logic();
      for (int i=0;i<=20;i++) {
        String string = input.nextLine();
        obj.myLogic(string);
        obj.printList();
      }
 }
 public void myLogic(String strObj) {
   if (this.list.size()>=10) {
      this.list.remove(this.list.size()-1);
   } else {
     list.add(strObj); 
   }
 }
 public void printList() {
 System.out.print(this.list);
 }
}

-2

Tôi đã có một vấn đề tương tự, cố gắng thêm một phần tử ở đầu một mảng hiện có, dịch chuyển các phần tử hiện có sang bên phải và loại bỏ phần tử cũ nhất (mảng [length-1]). Giải pháp của tôi có thể không hiệu quả lắm nhưng nó hoạt động cho mục đích của tôi.

 Method:

   updateArray (Element to insert)

     - for all the elements of the Array
       - start from the end and replace with the one on the left; 
     - Array [0] <- Element

Chúc may mắn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.