Java ArrayLista cómo agregar elementos al principio

183

Necesito agregar elementos a una ArrayListcola, pero cuando llamo a la función para agregar un elemento, quiero que agregue el elemento al comienzo de la matriz (por lo que tiene el índice más bajo) y si la matriz tiene 10 elementos agregando un nuevo resultado elimina el elemento más antiguo (el que tiene el índice más alto).

¿Alguien tiene alguna sugerencia?

ZeDonDino
fuente
¿Quieres decir como removey add?
Peter Lawrey
Para qué está usando su arraylist stack queue whateverpara agregar al inicio de una matriz, es mejor evitarlo y parece que debería estar usando una colección diferente.
Peter Lawrey
Primero, debes hacer algo tú mismo. ¿Que has hecho hasta ahora?
Yegoshin Maxim

Respuestas:

301

Listtiene el método add(int, E), por lo que puede usar:

list.add(0, yourObject);

Luego puede eliminar el último elemento con:

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

Sin embargo, es posible que desee repensar sus requisitos o utilizar una estructura de datos diferente, como un Queue

EDITAR

Quizás eche un vistazo a Apache CircularFifoQueue:

CircularFifoQueue es una cola de primero en entrar, primero en salir con un tamaño fijo que reemplaza su elemento más antiguo si está lleno.

Simplemente inicialícelo con su tamaño máximo:

CircularFifoQueue queue = new CircularFifoQueue(10);
Baz
fuente
10
No tocaría ninguna biblioteca apache con un poste de diez pies, especialmente porque existen las clases de colección de guayaba. EvictingQueue de Guava podría ser una buena opción aquí.
DPM
26

Usar estructuras de datos específicas

Existen varias estructuras de datos que están optimizadas para agregar elementos en el primer índice. Sin embargo, tenga en cuenta que si convierte su colección en una de estas, la conversación probablemente necesitará una complejidad de tiempo y espacio deO(n)

Deque

El JDK incluye la Dequeestructura que ofrece métodos como addFirst(e)yofferFirst(e)

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

Análisis

La complejidad de inserción en el espacio y el tiempo es con LinkedListconstante ( O(1)). Ver la hoja de trucos Big-O .

Revertir la lista

Un método muy fácil pero ineficiente es usar el reverso:

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

Si usa secuencias Java 8, esta respuesta podría interesarle.

Análisis

  • Complejidad del tiempo: O(n)
  • Complejidad espacial: O(1)

Al observar la implementación de JDK, esto tiene una O(n)complejidad temporal, por lo que solo es adecuado para listas muy pequeñas.

Patrick Favre
fuente
Invertir una lista dos veces. ¿Agregará el tiempo de ejecución del algoritmo por un gran margen en comparación con la solución aceptada anteriormente?
Samyak Upadhyay
Agrega 2n, así que sí, pero si tiene una lista de <50, no sería capaz de hacer una micro-referencia de la diferencia en la mayoría de las máquinas modernas
Patrick Favre el
8

Puede echar un vistazo a add (int index, E element) :

Inserta el elemento especificado en la posición especificada en esta lista. Desplaza el elemento actualmente en esa posición (si existe) y cualquier elemento posterior a la derecha (agrega uno a sus índices).

Una vez que agregue, puede verificar el tamaño de ArrayList y eliminar los que están al final.

npinti
fuente
4

Es posible que desee mirar Deque. le brinda acceso directo al primer y último elemento de la lista.

Evvo
fuente
1
Me sorprende que sea la única respuesta hablando de Deque, esta es obviamente la mejor solución óptima.
Guillaume F.
3

Lo que está describiendo es una situación apropiada para usar Queue.

Ya que quieres un addelemento nuevo, y removeel viejo. Puede agregar al final y eliminar desde el principio. Eso no hará mucha diferencia.

Queue tiene métodos add(e)y remove()que agrega al final el nuevo elemento, y elimina desde el principio el elemento anterior, respectivamente.

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

Por lo tanto, cada vez que agregue un elemento al queuepuede respaldarlo con una removellamada al método.


ACTUALIZACIÓN : -

Y si desea corregir el tamaño de laQueue , entonces puede echar un vistazo a: -ApacheCommons#CircularFifoBuffer

De la documentation: -

CircularFifoBuffer es un búfer primero en entrar, primero en salir con un tamaño fijo que reemplaza su elemento más antiguo si está lleno.

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

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

Como puede ver, cuando se alcanza el tamaño máximo, al agregar un nuevo elemento, se elimina automáticamente el primer elemento insertado.

Rohit Jain
fuente
1

Creo que la implementación debería ser fácil, pero teniendo en cuenta la eficiencia, debe usar LinkedList pero no ArrayList como contenedor. Puede consultar el siguiente código:

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);
        }
    }
}
feikiss
fuente
0

puedes usar este código

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);
    }
}
MaVRoSCy
fuente
0

Puede usar métodos de lista, eliminar y agregar

list.add(lowestIndex, element);
list.remove(highestIndex, element);
Yo_
fuente
0

Tome este ejemplo:

List<String> element1 = new ArrayList<>();
element1.add("two");
element1.add("three");
List<String> element2 = new ArrayList<>();
element2.add("one");
element2.addAll(element1);
Ashish Mehta
fuente
-1

Puedes usar

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

}

Cambie E con su tipo de datos

Si es necesario eliminar el elemento más antiguo, puede agregar:

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

antes de la declaración de devolución. De lo contrario, list agregará su objeto al principio y también retendrá el elemento más antiguo.

Esto eliminará el último elemento en la lista.

un alumno
fuente
-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);
 }
}
Machhindra Neupane
fuente
-2

Tuve un problema similar al intentar agregar un elemento al comienzo de una matriz existente, desplazar los elementos existentes a la derecha y descartar el más antiguo (matriz [longitud-1]). Mi solución puede no ser muy eficiente pero funciona para mis propósitos.

 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

Buena suerte

FabianUx
fuente