如何在Java数组列表开始添加元素

我需要向ArrayList队列添加元素,但当我调用函数添加一个元素时,我希望它在数组的开头添加元素(因此它有最低的索引),如果数组有10个元素,添加一个新元素会删除最老的元素(具有最高索引的元素)。

有人有什么建议吗?

426397 次浏览

List有方法add(int, E),所以你可以使用:

list.add(0, yourObject);

然后你可以删除最后一个元素:

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

但是,您可能需要重新考虑您的需求或使用不同的数据结构,如Queue

编辑

也许可以看看Apache的CircularFifoQueue:

CircularFifoQueue是一个先进先出队列,具有固定大小,如果已满则替换其最老的元素。

用你的最大大小初始化它:

CircularFifoQueue queue = new CircularFifoQueue(10);

你可以看一下add(int index, E element):

将指定元素插入到列表的指定位置。 移动当前位于该位置(如果有)的元素 右边的后续元素(给它们的下标加1).

一旦你添加了数组列表,你就可以检查数组列表的大小,并删除末尾的数组列表。

你所描述的是使用Queue的适当情况。

因为你想要add新元素,而remove旧元素。你可以在结尾添加,也可以从开头删除。那不会有太大区别。

Queue有方法add(e)remove(),它们分别在结尾添加新元素,并从开头删除旧元素。

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

因此,每当你向queue添加一个元素时,你可以用remove方法调用来备份它。


更新: -

如果你想要来固定Queue的大小,那么你可以看看:- ApacheCommons#CircularFifoBuffer

documentation: -

CircularFifoBuffer是一个固定大小的先进先出缓冲区

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


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

如您所见,当达到最大大小时,添加新元素将自动删除插入的第一个元素。

您可以使用此代码

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);
}
}

你可以使用

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


}

使用数据类型更改E

如果需要删除最老的元素,则可以添加:

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

在return语句之前。否则list将在开始时添加对象并保留最古老的元素。

这将删除列表中的最后一个元素。

我认为实现应该很简单,但是考虑到效率,你应该使用LinkedList而不是ArrayList作为容器。你可以参考以下代码:

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);
}
}
}

使用特定的数据结构

有各种各样的数据结构经过优化,可以在第一个索引处添加元素。不过请注意,如果您将您的集合转换为其中一个,对话可能需要O(n)的时间和空间复杂度

双端队列

JDK包括Deque结构,它提供了像addFirst(e)offerFirst(e)这样的方法

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

分析

插入的空间和时间复杂度为LinkedList常量(O(1))。参见大0备忘单

反转列表

一个非常简单但效率很低的方法是使用reverse:

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

如果你使用Java 8流,这个答案可能会让你感兴趣

分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

看看JDK实现,它有一个O(n)的时间复杂度,所以只适合非常小的列表。

您可以使用列表方法,删除和添加

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

你可能想看看Deque。它使您可以直接访问列表中的第一个和最后一个项。

Java LinkedList提供了addFirst(E E)和push(E E)方法,用于将元素添加到列表前面。

https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#addFirst(E)

我有一个类似的问题,试图在现有数组的开头添加一个元素,将现有元素向右移动,并丢弃最古老的一个(数组[length-1])。 我的解决方案可能不是很有效,但它符合我的目的。

 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

祝你好运

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);
}
}

举个例子:-

List<String> element1 = new ArrayList<>();
element1.add("two");
element1.add("three");
List<String> element2 = new ArrayList<>();
element2.add("one");
element2.addAll(element1);
import com.google.common.collect.Lists;


import java.util.List;


/**
* @author Ciccotta Andrea on 06/11/2020.
*/
public class CollectionUtils {


/**
* It models the prepend O(1), used against the common append/add O(n)
* @param head first element of the list
* @param body rest of the elements of the list
* @return new list (with different memory-reference) made by [head, ...body]
*/
public static <E> List<Object> prepend(final E head, List<E> final body){
return Lists.asList(head, body.toArray());
}


/**
* it models the typed version of prepend(E head, List<E> body)
* @param type the array into which the elements of this list are to be stored
*/
public static <E> List<E> prepend(final E head, List<E> body, final E[] type){
return Lists.asList(head, body.toArray(type));
}
}

带FIFO规则的有界循环缓冲区

看来你需要一个容量有限的循环缓冲区。 您更喜欢类似数组的行为,而不喜欢链接队列。 我说的对吗? 您似乎需要将容量设置为“10”。 这可以通过有界结构实现。

.你似乎也需要先进先出原则

使用ArrayBlockingQueue的解决方案

有界阻塞队列由数组支持…排序元素FIFO(先进先出)。队列的头是在队列上停留时间最长的元素。队列的尾部是在队列上停留时间最短的元素。在队列尾部插入新元素,队列检索操作获取队列头部的元素。 放,拿都挡。

.提议,投票不阻止

PriorityBlockingQueue

你可以看看PriorityBlockingQueue的文档。有一个类的例子,它将先进先出的规则应用于类似的元素。

ArrayBlockingQueue的示例

ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);


for (int i = 10; i < 30; i++) {
if (queue.remainingCapacity() > 0) {
queue.offer(i);
} else {
queue.poll();
queue.offer(i);
}
if (queue.size() > 9) {
System.out.println(queue);
}
}