Java ArrayList como adicionar elementos no início

183

Eu preciso adicionar elementos a um ArrayList fila, mas quando chamo a função para adicionar um elemento, quero que adicione o elemento no início da matriz (para que tenha o índice mais baixo) e se a matriz tiver 10 elementos adicionando um novo resulta na exclusão do elemento mais antigo (aquele com o índice mais alto).

Alguém tem alguma sugestão?

ZeDonDino
fonte
Você quer dizer como removee add?
22412 Peter Lawrey
O que você está usando arraylist stack queue whateverpara adicionar ao início de uma matriz é melhor evitar e parece que você deve usar uma coleção diferente.
22412 Peter Lawrey
Primeiro, você deve fazer algo você mesmo. O que você fez até agora?
Yegoshin Maxim 18/10/12

Respostas:

301

Listtem o método add(int, E), então você pode usar:

list.add(0, yourObject);

Depois, você pode excluir o último elemento com:

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

No entanto, convém repensar seus requisitos ou usar uma estrutura de dados diferente, como um Queue

EDITAR

Talvez dê uma olhada no Apache CircularFifoQueue:

CircularFifoQueue é uma fila primeiro a entrar, primeiro a sair, com um tamanho fixo que substitui o elemento mais antigo, se estiver cheio.

Apenas inicialize com seu tamanho máximo:

CircularFifoQueue queue = new CircularFifoQueue(10);
Baz
fonte
10
Eu não tocaria em nenhuma biblioteca apache com um poste de três metros, principalmente porque existem classes de coleção de goiaba. O EvictingQueue da Guava pode ser uma boa escolha aqui.
DPM
26

Usando estruturas de dados específicas

Existem várias estruturas de dados que são otimizadas para adicionar elementos no primeiro índice. No entanto, lembre-se de que, se você converter sua coleção para uma delas, a conversa provavelmente precisará de uma complexidade de tempo e espaço deO(n)

Deque

O JDK inclui a Dequeestrutura que oferece métodos como addFirst(e)eofferFirst(e)

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

Análise

A complexidade do espaço e do tempo de inserção é LinkedListconstante ( O(1)). Veja a folha de dicas do Big-O .

Invertendo a lista

Um método muito fácil, mas ineficiente, é usar reverse:

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

Se você usa fluxos Java 8, esta resposta pode lhe interessar.

Análise

  • Complexidade temporal: O(n)
  • Complexidade espacial: O(1)

Olhando para a implementação do JDK, isso tem uma O(n)complexidade de tempo, sendo adequado apenas para listas muito pequenas.

Patrick Favre
fonte
Invertendo uma lista duas vezes. Adicionará o tempo de execução do algoritmo por uma grande margem em comparação com a solução aceita acima?
21817 Samyak Upadhyay
Acrescenta 2N, então sim, mas se você tem lista de <50 você não seria capaz de micro referência a diferença na maioria das máquinas modernas
Patrick Favre
8

Você pode dar uma olhada no add (int index, elemento E) :

Insere o elemento especificado na posição especificada nesta lista. Desloca o elemento atualmente nessa posição (se houver) e quaisquer elementos subsequentes para a direita (adiciona um aos seus índices).

Depois de adicionar, você pode verificar o tamanho do ArrayList e removê-los no final.

npinti
fonte
4

Você pode querer olhar para Deque. fornece acesso direto ao primeiro e ao último itens da lista.

Evvo
fonte
1
Estou surpreso que você seja a única resposta falando sobre o Deque, essa é obviamente a melhor solução ideal.
Guillaume F.
3

O que você está descrevendo é uma situação apropriada para usar Queue .

Desde que você deseja addnovo elemento, eremove o antigo. Você pode adicionar no final e remover do início. Isso não fará muita diferença.

A fila possui métodos add(e)e remove()que adiciona ao final o novo elemento e remove desde o início o elemento antigo, respectivamente.

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

Portanto, toda vez que você adiciona um elemento ao queuevocê pode fazer backup com uma removechamada de método.


ATUALIZAÇÃO : -

E se você quiser corrigir o tamanho doQueue , poderá dar uma olhada em: -ApacheCommons#CircularFifoBuffer

Desde documentation: -

O CircularFifoBuffer é um buffer primeiro a entrar, com um tamanho fixo que substitui o elemento mais antigo se estiver cheio.

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

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

Como você pode ver, quando o tamanho máximo é atingido, a adição de um novo elemento remove automaticamente o primeiro elemento inserido.

Rohit Jain
fonte
1

Eu acho que o implemento deve ser fácil, mas considerando a eficiência, você deve usar o LinkedList, mas não o ArrayList como contêiner. Você pode consultar o seguinte 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
fonte
0

você pode usar esse 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
fonte
0

Você pode usar métodos de lista, remover e adicionar

list.add(lowestIndex, element);
list.remove(highestIndex, element);
Eu_
fonte
0

Veja este exemplo: -

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

Você pode usar

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

}

Mude E com seu tipo de dados

Se a exclusão do elemento mais antigo for necessária, você poderá adicionar:

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

antes da declaração de retorno. Caso contrário, a lista adicionará seu objeto no início e também manterá o elemento mais antigo.

Isso excluirá o último elemento da lista.

um aprendiz
fonte
-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
fonte
-2

Eu tive um problema semelhante, tentando adicionar um elemento no início de uma matriz existente, mudar os elementos existentes para a direita e descartar o mais antigo (matriz [comprimento-1]). Minha solução pode não ter muito desempenho, mas funciona para meus 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

Boa sorte

FabianUx
fonte