I'm looking for a data structure that is basically a bounded stack.
If I declare that the stack can hold at most 3 items, and I push another item in,
the oldest item is popped.
You'll be able to implement this using a wrapper over a deque (http://en.wikipedia.org/wiki/Deque), or double-ended queue. Just make sure to call the pollLast method inside the offerFirst method if the stack size is reached.
I'd write my own Deque implementation based on a ring buffer.
You need a queue. A singly linked list that records the first and last items.
A doubly linked one if you would like to change from O(n) to O(1) traversal to update the last item.
You push objects at the front of the queue. And if the length is greater than 3, you pop the back.
Well a LIFO (Last In First Out) structure is known as a Stack which is what you need for the main part of your requirement
A FIFO (First In First Out) structure is known as a Queue which is what you need for the ability to pop the oldest Items off the back.
A combination of these is known as a Deque. Where you have to the ability to push or pop from either end.
I'm not sure if Java has a built-in Deque datastructure, but if it does (or you can find an implementation on google), You can just put some wrapping logic around to ensure that if you push to the front, and the deque.Count > 3, then also pop from the back.
This is in C# as I don't know Java I'm afraid but the idea should translate.
public class BoundedStack<T>
{
private readonly int limit;
private LinkedList<T> list;
public BoundedStack(int limit)
{
this.limit = limit;
list = new LinkedList<T>();
}
public void Push(T item)
{
if (list.Count == limit) list.RemoveFirst();
list.AddLast(item);
}
public T Pop()
{
if (list.Count == 0)
throw new IndexOutOfRangeException("No items on the stack");
var item = list.Last.Value;
list.RemoveLast();
return item;
}
public int Count()
{
return list.Count;
}
}
Apache commons has something close to what you need except it is Fifo: CircularFifoBuffer. I think you will be stuck writing a custom wrapper to make a Lifo like implementation.
Here is my LIFO implementation, inspired by Garry Shutler's answer
public class BoundedStack<T> {
private int limit;
private LinkedList<T> list;
public BoundedStack(int limit) {
this.limit = limit;
list = new LinkedList<>();
}
public void push(T item) {
if (list. size() == limit) {
list.removeLast();
}
list.addFirst(item);
}
public int size() {
return list.size();
}
public List<T> getAll() {
return list;
}
public T peek() {
return list.get(0);
}
}
Related
I'm using the Deque to implement a monotonic queue. I know that Deque can be created by both ArrayDeque and LinkedList. Here is the Monotonic class I constructed:
public static class MonotonicQueue {
Deque<Integer> monotonicQueue;
public MonotonicQueue() {
monotonicQueue = new ArrayDeque<>();
}
void push(int n) {
while (!monotonicQueue.isEmpty() && monotonicQueue.getLast() < n) {
monotonicQueue.removeLast();
}
monotonicQueue.addLast(n);
}
int max() {
return monotonicQueue.getFirst();
}
void pop(int n) {
if (!monotonicQueue.isEmpty() && n == monotonicQueue.getFirst()) {
monotonicQueue.removeFirst();
}
monotonicQueue.addLast(n);
}
}
However, the issue appears in the void push(int n) method, which means delete all elements which are < n, and then add n into the queue of the tail. I initialized a variable window in a method and then tried to push an element to update this monotonic queue.
MonotonicQueue window = new MonotonicQueue();
window.push(3);
But it even fails to insert the first element. The weird thing is when I use the second way in the constructor, say LinkedList<> instead of ArrayDeque, it works very well, i.e. 3 can be inserted successfully.
public MonotonicQueue() {
monotonicQueue = new LinkedList<>();
}
I am wondering why one way works but the other can't. What happened here? Thank you!
How do you code an Iterator for a Set? Given that the iterator does not have access to the underlying data storage mechanism, and can only use the Set methods, is it possible to do this?
Every implementation I've managed to find creates the Iterator as an anonymous class; however, I am trying to figure out if there is a clever way to iterate over a Set while only accessing the methods provided by Set.
So far, the best I've managed to come up with looks like this:
import java.util.*;
public class SetIterator<E> implements Iterator
{
protected E[] arrayData;
protected Set<E> set;
protected int index;
protected boolean canRemove;
public SetIterator(Set<E> set)
{
this.set = set;
this.arrayData = (E[]) set.toArray();
this.index = -1;
this.canRemove = false;
}
public E next()
{
if(this.hasNext())
{
this.canRemove = true;
return this.arrayData[++this.index];
}
else
{
throw new NoSuchElementException("There is no next element");
}
}
public boolean hasNext()
{
return this.index + 1 < this.arrayData.length;
}
public void remove()
{
if(this.canRemove)
{
this.set.remove(this.arrayData[index--]);
this.arrayData = (E[]) this.set.toArray();
this.canRemove = false;
}
else
{
throw new IllegalStateException("Cannot remove element before calling next");
}
}
}
But that feels quite kludgy.... Is there a better way?
I think your title doesn't leave much space for answers, but if I use the following as your actual question:
How do you build an Iterator for a Set?
(and understand build as in get an instance of)
I think as PM 77-1 pointed out in the comments:
call the iterator() method on it, which it has since at least Java 1.5.
Keep in mind that it depends on the actual implementation of Set, wether the elements will always be iterated over in the same order.
if we look in AbstractCollection we will see that toArray actually calls the iterator() (abstract method) to produce the array which you will use, so your method still depends on the specific iterator, so you are essentially decorating the iterator.
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
Still not sure what you are trying to accomplish, the underlying datastructure of the set will have different (and specific) ways to efficently iterate the data, any generic solution would sacrafice performance, using the iterable interface should be generic enough.
I have a java object that implements the Iterable interface. This linked list has a group of objects that each hold a parameterized object (so it could be a String OR an ArrayList or whatever).
In the iterator() method, i create an Iterator object that takes an array of these parameterized items and return it.
However, when i use the following code:
//create an Iterable object named 'iterate'
for(String current : iterate){
//try to do some stuff with it... print it out?
}
//more code
//here is how i implemented the iterator function of my Iterable class:
public Iterator<Item> iterator(){
// return an iterator over items in order from front to end
Item[] items = (Item[]) new Object[numberOfItems];
QueueItem<Item> item = first;
for(int i=0;i<numberOfItems;i++){
items[i] = item.getInfo();
item = item.next;
}
return new myIterator(items);
}
//here is the code for the myIterator class. it is a private internal class
private class myIterator implements Iterator<Item>{
Item items[];
int index;
public myIterator(Item current[]){
items = current;
index = 0;
}
#Override
public boolean hasNext() {
if(items==null){
return false;
}
return (index>=items.length);
}
#Override
public Item next() {
if(index+1>=items.length){
throw new NoSuchElementException("There are no more elements!");
}
return items[index++];
}
#Override
public void remove() {
throw new UnsupportedOperationException("this operation is not supported");
}
}
the code goes to the for loop, then creates the Iterator object correctly (I used breakpoints to confirm), and returns it, but then the code jumps out of the for loop without going through it even once and continues....
Am i missing something? did i do something wrong here? how do i need to change the implementation of my Iterable object? is there some GOTCHA with implementing this that i'm not taking into account?
thanks!
in hasNext method you check if return (index>=items.length); Well this will return false. change operant to "<"
oh my gosh. so embarrassing. the hasNext method had the boolean statement reversed.
it should have been:
return (index<items.length); thanks anyways!
i've been pulling my hair out about this. i debugged everything else, then it dawned on me.
This is my first iterator implementation, so i figured it must have been something more fundamental that i wasn't doing correctly.
Is there a way to give size limit to TreeSet in Java Collections as we do for arrays?
for example in arrays we do,
anArray = new int[10];
An array has a fixed length that must be specified when you create it.
A TreeSet automatically grows as you add elements to it. You cannot set its size. You can only read it.
This threat can help you fixed size list in Java
Also, you can implement your own collection in order to add elements if your limit has not been reached
You can always make your own implementation. Here is an example to get you started; you may find that you wish to tweak it accordingly:
public class BoundedTreeSet<E> extends TreeSet<E> {
private final int limit;
public BoundedTreeSet(final int limit) {
super();
this.limit = limit;
}
public BoundedTreeSet(final int limit, final Collection<? extends E> c) {
super(c);
this.limit = limit;
}
public BoundedTreeSet(final int limit, final Comparator<? super E> comparator) {
super(comparator);
this.limit = limit;
}
public BoundedTreeSet(final int limit, final SortedSet<E> s) {
super(s);
this.limit = limit;
}
#Override
public boolean add(final E e) {
if (size() >= limit) {
return false;
}
return super.add(e);
}
#Override
public boolean addAll(Collection<? extends E> c) {
if (size() + c.size() >= limit) {
return false;
}
return super.addAll(c);
}
}
None of TreeSet's constructors specifies an initial size, it grows when elements are added. And there's no way to limit the maximum size of the data structure. Every time you add() a new element, you'd need to manually check if it has exceeded the maximum size allowed. You can specify this behavior by implementing a subclass that extends from TreeSet and overriding add(), addAll(), and the two constructors that receive a Collection as a parameter.
Here is an implementation of BoundedTreeSet in Apache Solr, which keeps the biggest values when trying to insert into a "full" set :
http://lucene.apache.org/solr/4_6_0/solr-core/org/apache/solr/util/BoundedTreeSet.html
Maven artifact available here :
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-core</artifactId>
<version>4.6.0</version>
</dependency>
The closest you can come to an existing collection with capacity limits is a BlockingQueue. When adding items to the queue, you can specify a zero second (or very small) blocking timeout, so that an exception is thrown when the capacity is exceeded. For more details, see BlockingQueue.offer()
i am a novice programmer, to be specific, i am learning java programming and i am supposed to implement sortedLinkedList class that extends LinkedList class from the java library. The list has to store persons in ascending order of their surnames. I have already written my Person class that implements Comparable interface. my problem is, I have been struggling implementing this sortedLinkedClass but to no avail. My code runs without any compiling or run time error but the program does not print anything. Another thing as you can see , I am testing it with Integers instead of Persons and it throws NullPointerException when trying to add a number that is already in the list. My code is as it is below.
import java.util.*;
public class SortedLinkedList< E> extends LinkedList<E>
{
private Link<E> first;
private Link<E> last;
/**
* Constructor for objects of class SortedLinkedList
*/
public SortedLinkedList()
{
//super();
first = null;
last = null;
}
/*
* Link class for creating Link nodes in the SortedLinkedList objects
*/
private class Link<E>
{
public Comparable<E> data;
public Link next;
}
/*
* Overiding add method from LinkedList class
*/
public boolean add(E obj)
{
Link newLink = new Link();
newLink.data = (Comparable<E>)obj;
// When the list is initially empty
if (first == null)
{
first = newLink;
last = newLink;
return true;
}
// When the element to be added is less than the first element in the list
if (newLink.data.compareTo(first.data) < 0)
{
//newLink.data = obj;
newLink.next = first;
first = newLink;
return true;
}
// When the element to be added is greater than every element in in list
// and has to be added at end of the list
if (newLink.data.compareTo(last.data) > 0)
{
//newLink.data = obj;
last.next = newLink;
last = newLink;
return true;
}
//When the element to be added lies between other elements in the list
if (newLink.data.compareTo(first.data) >= 0 && newLink.data.compareTo(last.data) <= 0)
{
//newLink.data = obj;
Link current = first.next;
Link previous = first;
while (newLink.data.compareTo(current.data) <= 0)
{
previous = current;
current = current.next;
}
previous.next = newLink;
newLink.next = current;
}
return true;
}
public static void main (String[] args)
{
LinkedList<Integer> list = new SortedLinkedList<Integer>();
list.add(4);
list.add(5);
list.add(10);
list.add(9);
//list.add(5);
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext())
{
System.out.println(iterator.next());
}
}
}
If you must use a LinkedList, all you really have to do is override the "add" method so that it inserts your element in the correct position. You can do that by invoking the add(integer,Object) method which inserts your element in a specific position.
Here's a quick and dirty (and non-generic :P) implementation of what I'm talking about.
public class PersonLinkedList extends LinkedList<Person> {
public boolean add(Person personToAdd) {
int index = 0;
for( ; index<size() ; index++){
Person personAlreadyInList = get(index);
if(personToAdd.compareTo(personAlreadyInList) < 0){
break;
}
}
add(index, personToAdd);
return true;
};
public static void main(String[] args) {
Person amy = new Person("Amy");
Person bob = new Person("Bob");
Person claire = new Person("Claire");
PersonLinkedList list = new PersonLinkedList();
list.add(bob);
list.add(claire);
list.add(claire);
list.add(amy);
list.add(bob);
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Person person = (Person) iterator.next();
System.out.println(person);
}
}
}
class Person implements Comparable<Person>{
private String name;
public Person(String name) { this.name = name; }
public String getName() { return name; }
#Override
public String toString() { return getName();}
#Override
public int compareTo(Person p) {
return name.compareTo(p.name);
}
}
The reason nothing gets printed is because you store the data in your own linked list data tree and not the LinkedList's data tree. You don't override the iterator method, so the iterator will loop through LinkedList's data which is empty. This is also a problem with all the other methods in LinkedList.
Are you sure you need to inherit from the LinkedList class or are you suppose to make your own class.
If you are supposed to inherit from LinkedList get rid of you node and use LinkedList for storing the data. Your add method would then use a ListIterator to find the correct spot for adding and use the add method of ListIterator.
If you don't inherit from LinkedList then extend AbstractSequentialList.
Note:
Both of these options should not be used in real code. Adding automatic sorting breaks the List interface.
The whole problem is a perfect example of "prefer composition over inheritance".
If this is homework do it as instructed, otherwise I'd recommend changing the exercise to implement a SortedCollection backed by a LinkedList. Then implement Collection and use a List as a member variable.
You could use a SortedSet if you don't need to support elements with the same sort key.
Also, the reason your code doesn't print anything is because you override adding items to the list, but not iterating (the iterator() or listIterator() methods.) Extending LinkedList doesn't automagically make your data structure iterable unless you modify its contents using the base class add(), remove(), and other methods.
besides iterator, add/remove override, I think your algorithm to sort is not correct. And that leads to the nullpointer exception when you add existing elements into your "sortedLinkedList".
while (newLink.data.compareTo(current.data) <= 0)
{
previous = current;
current = current.next;
}
I think what you wanted is while (newLink.data.compareTo(current.data) >0) . not <=0. here is the mistake.
since "=0" is in while condition, it will go through the whole list, till the last element, then execute:
(current is the last now)
previous = current;
current = current.next; (now, current is Null, since last.next is Null)
finally, current is Null, then comes again, current = current.next; Bang! Nullpointer.
so I guess the Nullpointer was thrown at this line.