开发者

How to leftshift an ArrayList

开发者 https://www.devze.com 2023-03-10 15:41 出处:网络
I\'m using an ArrayList to hold a history of objects. Each new object I add using the .add method, like:

I'm using an ArrayList to hold a history of objects. Each new object I add using the .add method, like:

if(event.getActio开发者_开发知识库n() == MotionEvent.ACTION_UP)
{
    if(currentWord != null)
    {
        wordHist.add(currentWord);
    }

    if(wordHist.size() > WORDHIST_MAX_COUNT)
    {
        wordHist.remove(0);
    }
}

However I don't want this to grow indefinitely, but to be limited to a certain value. If it reaches this maximum value, I want the oldest object (index 0) to be removed, and the rest to be left shifted, so previous index 1 is now index 0, etc.

How can this be done?

Thanks


ArrayList is not really a good choice in this case, but it can by done by calling remove(0) method. But if you want to do that efficiently, a linked list is better

(edited to make it clear that LinkedList is not generally better than ArrayList, but only in this case)


If it reaches this maximum value, I want the oldest object (index 0) to be removed

Then do wordHist.remove(0). That will remove the element at index 0.

To be precise:

wordHist.add(new Word("hello"));
if (wordHist.size() > MAX_SIZE)
    wordHist.remove(0);

As user658991 states however, you should be aware of that this is a linear operation, i.e., takes time proportional to the number of elements in the list.

You could do this in constant time using LinkedList methods add and removeFirst.

Another option would be to wrap an array, or ArrayList in a class called something like CircularArrayList. In circular list structures you'll override the oldest element when adding a new one.

Edit:

Your code works fine:

import java.util.*;
class Test {
    
    static int WORDHIST_MAX_COUNT = 3;
    static List<String> wordHist = new ArrayList<String>();
    
    public static void add(String currentWord) {

        // VERBATIM COPY OF YOUR CODE

        if (true/*event.getAction() == MotionEvent.ACTION_UP*/)
        {
            if(currentWord != null)
            {
                wordHist.add(currentWord);
            }

            if(wordHist.size() > WORDHIST_MAX_COUNT)
            {
                wordHist.remove(0);
            }
        }
    }
    
    public static void main(String[] args) {
        add("a");
        add("b");
        add("c");
        
        for (int i = 0; i < wordHist.size(); i++)
            System.out.printf("i: %d, word: %s%n", i, wordHist.get(i));
        System.out.println();
        
        add("d");
        
        for (int i = 0; i < wordHist.size(); i++)
            System.out.printf("i: %d, word: %s%n", i, wordHist.get(i));
    }
}

Prints:

i: 0, word: a
i: 1, word: b
i: 2, word: c

i: 0, word: b        <-- b is now at index 0.
i: 1, word: c
i: 2, word: d


Use the remove( ) method.

Using remove(0) will remove the element from the 0th index.


U can use list.remove(index)// here index being '0', this internally shifts rest of the array up. An alternative solution wud be to use a queue or dequeue.


One simple implementation of what Op De Cirkel suggested

import java.util.ArrayList;
import java.util.List;


public class SimpleCircularHistory {

    private int sizeLimit, start = 0, end = 0;
    boolean empty = false;
    private List<String> history;

    public SimpleCircularHistory(int sizeLimit) {
        this.sizeLimit = sizeLimit;
        history = new ArrayList<String>(sizeLimit);
    }

    public void add(String state){ 
        empty = false;
        end = (end + 1) % sizeLimit;
        if(history.size() < sizeLimit){
            history.add(state);
        }else {
            history.set(end, state);
            start = (end + 1) % sizeLimit;
        }
    }

    public String rollBack(){
        if(empty){ // Empty
            return null;
        }else {
            String state = history.get(end);
            if(start == end){
                empty = true;
            }else {
                end = (end + sizeLimit - 1) % sizeLimit;
            }
            return state;
        }
    }

    public void print(){
        if(empty){
            System.out.println("Empty");
        }else {
            for(int i = start;; i = (i + 1) % sizeLimit){
                System.out.println(history.get(i));
                if(i == end) break;
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        SimpleCircularHistory h = new SimpleCircularHistory(3);
        h.add("a");
        h.add("b");
        h.add("c");
        h.add("d");
        h.add("e");
        h.add("f");
        h.print();

        h.add("X");
        h.add("Y");
        h.rollBack();
        h.rollBack();
        h.print();
        h.add("t");
        h.add("v");
        h.add("w");
        h.print();
        h.rollBack();
        h.rollBack();
        h.rollBack();
        h.print();
        h.rollBack();
        h.print();
    }

}

This would print out :

d
e
f

f

t
v
w

Empty
Empty


Yeah, I've noticed this behaviour in adroid's lists too. It's REALLY irritating.

Anyway, there is a way to get around it if I don't mind object creation/destruction and the resulting garbage collection (NEVER do this in a onDraw of a surfaceview or something).

What I do is basically have two tracking int's; one to place the new object, and one to remove it:

                int trackInt = 0;
                int removeInt = 0;

                //and then, in the method/class you use this:

                Object newobject = new Object();
                //add to list
                objectList.add(trackInt, newobject);
                trackInt++;
                if (bugList.size() > 20) //20 is the max number of object you want, ie the maximum size of the list
                {
                    objectList.remove(removeInt);
                    trackInt = removeInt;
                    removeInt++;
                    if (removeInt > 19) //remember, the list is zero indexed!
                    {
                        removeInt = 0;
                    }
                }


Commons-collections has exactly what you're looking for:

http://commons.apache.org/collections/apidocs/org/apache/commons/collections/buffer/CircularFifoBuffer.html

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号