Create a LIFO stack system with discard when full in Java

I want to design a system, establishing a data store method, stack style, but with the peculiarity that when the maximum is reached (3) the first element of the stack is removed, so only keep the last values.

Overall design:

As long as a data can be stored that puts them one after another (1,2,3...)

1: A
2: B
3: C

If the stack is full and you want to add new data, the first item is deleted and done a rotation with the others, so that the last data entered is the last.

1: B
2: C
3: D

If another one is added (C, D, E) i.e. only the last 3 inserted data are saved.

The type of data to save that is custom class TextDataStatus The object of TextDataStatus

public class TextDataStatus {

    int action;
    String content;
    int start;
    int end;

    public TextDataStatus(int action, String content, int start, int end) {
        this.action = action;
        this.content = content;
        this.start = start;
        this.end = end;
    }

    public int getAction() {
        return action;
    }

    public void setAction(int action) {
        this.action = action;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getStart() {
        return start;
    }

    public void setStart(int start) {
        this.start = start;
    }

    public int getEnd() {
        return end;
    }

    public void setEnd(int end) {
        this.end = end;
    }

    @Override
    public String toString() {
        return "TextDataStatus{" +
                "action=" + action +
                ", content='" + content + '\'' +
                ", start=" + start +
                ", end=" + end +
                '}';
    }
}

The extraction method must be style LIFO (Last Input First Output) and that allows storing duplicate data.

 3
Author: Eslacuare, 2016-07-03

2 answers

Clarification:

You Say you want a LIFO (last in first out - the last one that comes in is the first thing that comes), but the example you provide is a FIFO (first in first out - the first thing that comes in is the first thing that comes), since these eliminating that was the first to enter.

But don't worry, whatever your case (I understand FIFO) someone already took care of the topic and Java has classes for it and even if they are not exactly what you need, they'll save us most of the work.


FIFO: Queue

The Queue object is a particular implementation of LinkedList, you can make the object stack have its own order based on the equals and hashCode of the objects it contains, but by default, it is a FIFO stack as you can see:

Example:

import java.util.LinkedList;
import java.util.Queue;

private final static String[] letras = { "A", "B", "C", "D", "E" };

Queue<String> fifo = new LinkedList<String>();

for (String s : letras) {
    fifo.add(s);
}

System.out.println(fifo);

while (!fifo.isEmpty()) {
    System.out.println("La que se añadio mas recientemente es " + fifo.remove());
    System.out.println(fifo);
}

Output:

[A, B, C, D, E]
La que se añadio mas recientemente es A
[B, C, D, E]
La que se añadio mas recientemente es B
[C, D, E]
La que se añadio mas recientemente es C
[D, E]
La que se añadio mas recientemente es D
[E]
La que se añadio mas recientemente es E
[]

LimitedFIFOList<E>

A from there, by making a wrapper class that protects the add methods, you can control the maximum size and have a limit getter other than size():

import java.util.LinkedList;

public class LimitedFIFOList<E> extends LinkedList<E> {
    private static final long serialVersionUID = 1L;
    private int limite;

    public LimitedFIFOList(int limite) {
        this.limite = limite;
    }

    @Override
    public boolean add(E o) {
        super.add(o);
        // si el tamaño fuera mayor eliminamos uno 
        while (size() > limite) { super.remove(); }
        return true;
    }

    public int getLimite() {
        return limite;
    }

    public void setLimite(int limite) {
        this.limite = limite;
    }    

}

Than using the example above:

private static void FIFO() {
    LimitedFIFOList<TextDataStatus> fifo = new LimitedFIFOList<TextDataStatus>(3);

    for (TextDataStatus d : datos) {
        fifo.add(d);
        System.out.println(fifo.toString());
    }
}

Output:

[TextDataStatus{action=1, content='A', start=1, end=6}
]
[TextDataStatus{action=1, content='A', start=1, end=6}
, TextDataStatus{action=1, content='B', start=2, end=7}
]
[TextDataStatus{action=1, content='A', start=1, end=6}
, TextDataStatus{action=1, content='B', start=2, end=7}
, TextDataStatus{action=1, content='C', start=3, end=8}
]
[TextDataStatus{action=1, content='B', start=2, end=7}
, TextDataStatus{action=1, content='C', start=3, end=8}
, TextDataStatus{action=1, content='D', start=4, end=9}
]
[TextDataStatus{action=1, content='C', start=3, end=8}
, TextDataStatus{action=1, content='D', start=4, end=9}
, TextDataStatus{action=1, content='E', start=5, end=10}
]

LIFO Collection: Stack

Since we are and the question is a little confusing, we will also explain the LIFO classes that Java has and how to put a limit to have the pair complete. For this, we will use Stack.

The Stack class represents a last-in-first-out (LIFO) stack of objects. It extends class Vector with five operations that allow a vector to be treated as a stack. The usual push and pop operations are provided, as well as a method to peek at the top item on the stack, a method to test for whether the stack is empty, and a method to search the stack for an item and discover how far it is from the top.

Example:

import java.util.Stack;

private final static String[] letras = { "A", "B", "C", "D", "E" };

Stack<String> st = new Stack<String>();

for (String s : letras) {
    st.add(s);
}

System.out.println(st.toString());  //     [A, B, C, D, E]
// cambiando el tamaño a menos de los objetos que contiene
// elimina los ultimos objetos añadidos
st.setSize(3);
System.out.println(st.toString());  //     [A, B, C]
// pop quita el que se haya añadido el ultimo
st.pop();
System.out.println(st.toString());  //    [A, B]

Output:

[A, B, C, D, E]
[A, B, C]
[A, B]

LimitedLIFOList<E>

If your case were this, the wrapper would be very similar, but with Stack

import java.util.Stack;

public class LimitedLIFOList<E> extends Stack<E> {
    private static final long serialVersionUID = 1L;
    private int limite;

    public LimitedLIFOList(int limite) {
        this.limite = limite;
    }

    @Override
    public boolean add(E o) {
        super.add(o);
        // si el tamaño fuera mayor eliminamos uno 
        while (size() > limite) { super.pop(); }
        return true;
    }

    public int getLimite() {
        return limite;
    }

    public void setLimite(int limite) {
        this.limite = limite;
    }
}

Example:

private static void LIFO() {
    LimitedLIFOList<TextDataStatus> lifo = new LimitedLIFOList<TextDataStatus>(3);

    for (TextDataStatus d : datos) {
        lifo.add(d);
        System.out.println(lifo);

        if (lifo.size() == lifo.getLimite())
            System.out.println("quitamos > " + lifo.pop());
    }
}

Output:

[TextDataStatus{action=1, content='A', start=1, end=6}
]
[TextDataStatus{action=1, content='A', start=1, end=6}
, TextDataStatus{action=1, content='B', start=2, end=7}
]
[TextDataStatus{action=1, content='A', start=1, end=6}
, TextDataStatus{action=1, content='B', start=2, end=7}
, TextDataStatus{action=1, content='C', start=3, end=8}
]
quitamos > TextDataStatus{action=1, content='C', start=3, end=8}

[TextDataStatus{action=1, content='A', start=1, end=6}
, TextDataStatus{action=1, content='B', start=2, end=7}
, TextDataStatus{action=1, content='D', start=4, end=9}
]
quitamos > TextDataStatus{action=1, content='D', start=4, end=9}

[TextDataStatus{action=1, content='A', start=1, end=6}
, TextDataStatus{action=1, content='B', start=2, end=7}
, TextDataStatus{action=1, content='E', start=5, end=10}
]
quitamos > TextDataStatus{action=1, content='E', start=5, end=10}

Notes:

  • to achieve your goal you must implement a LimitedFIFOList
  • looking for information I've seen that the Apache guys (like no... ^_^) already has an implementation called CircularFIFOQueue.
  • Eye because it is possible to change the size, if you want to make it fixed, overwrite the setSize() so that it does nothing.

    @Override
    public void setSize(int size) {
    }
    

I hope I have explained well and clarified your doubts, also if you have any doubts, syllable :).

 5
Author: Jordi Castilla, 2016-07-05 06:57:53

Solvent Thanks to the solution of @ Jordi_Castilla I have used the method LimitedLIFOList following his indications I have done the following:

public class LimitedLIFOList<E> extends Stack<E> {
    private int limite;

    public LimitedLIFOList(int limite) {
        this.limite = limite;
    }

    @Override
    public E push(E o) {
        super.push(o);
        if (size() > limite) { super.remove(0); }
        return o;
    }
}

Test:

LimitedLIFOList<TextDataStatus> fifo2 = new LimitedLIFOList<>(3);

fifo2.push(new TextDataStatus(1,"A",0,0));
fifo2.push(new TextDataStatus(1,"B",0,0));
fifo2.push(new TextDataStatus(2,"C",0,0));
fifo2.push(new TextDataStatus(1,"D",0,0));
fifo2.push(new TextDataStatus(1,"E",0,0));
fifo2.push(new TextDataStatus(3,"F",3,1));

Result:

I/System.out: TextDataStatus{action=1, content='D', start=0, end=0}
I/System.out: TextDataStatus{action=1, content='E', start=0, end=0}
I/System.out: TextDataStatus{action=3, content='F', start=3, end=1}
 1
Author: Webserveis, 2016-07-04 18:34:27