What should be considered to make a mutable class immutable? For example: Can we still have push and pop methods in an immutable stack class? Or we should simply remove any method that changes the state of the instantiated object?
The bottom line is: You'd be better to remove the method modifying the state of the instantiated object from the class. But if you want to keep it, then it should create a new object with a different state from the original one and return the new object back.
Here is a more specific answer:
There shouldn't be any methods changing the object state in an immutable class.
There are a lot of void methods which change the state of this object in a mutable class. So we should change the signature of them in a way the return a new object instead of changing "this" object's state.
Also there are a lot of non-void methods which change the state of "this" object and return the value they changed in "this". The signature of these methods should also be changed in a way that they return a new object instead of changing the state of "this". Talking about lists, usually another method (like "peek") is also needed to get a certain value. Check the sample bellow to get what do I mean:
Check out these "push" and "pop" methods for a mutable stack class:
public class Stack <E> {
…
public void push (E e) {
ensureCapacity(); // This method checks for capacity
elements[size++] = e;
}
This method adds a new element at the top of the stack and changes the state of "this" object in this way.
public E pop () {
if (size == 0) throw new IllegalStateException("Stack.pop");
E result = elements[--size];
elements[size] = null;
return result;
}
…
}
This method removes the element at the top of the stack and returns it back and changes the state of "this" object by removing the element.
Now, suppose that we need to change these methods to make this stack immutable. Let's deal with "push" method first:
"push" is a void method which changes the state of "this" object by adding a new element to it. To make the stack immutable we will create a new stack similar to "this" and add the new element to this new stack and return it back:
public class ImmStack <E> {
...
/**
* this method pushes the item to a new object and keeps the original object unchanged
* #param e The item to be pushed
* #return A new list
* #PRE An original list object is required as well as an item to be pushed
* #POST A new list would be returned
*/
#SuppressWarnings({ "unchecked", "rawtypes" }) // All items in this.elements[] are of type E
public ImmStack<E> push (E e) {
ImmStack<E> stc = new ImmStack(getNewElements());
stc.elements=ensureCapacity(stc.elements);
stc.elements[size] = e;
stc.size = size +1;
return stc;
}
"pop" method changes the state of "this" object by removing an element. To make the class immutable we will reate a new stack similar to "this" and remove the element from this new stack and return it back:
/**
* This pop method returns a new stack without the element at the top of the original list
* #return The new stack
* #POST The new stack would be returned
*/
#SuppressWarnings({ "unchecked", "rawtypes" }) // All items in this.elements[] are of type E
public ImmStack<E> pop () {
if (size == 0) throw new IllegalStateException("Stack.pop");
ImmStack<E> stc = new ImmStack(getNewElements());
stc.elements=ensureCapacity(stc.elements);
stc.elements[size-1] = null;
stc.size=size-1;
return stc;
}
The old "pop" method was returning the element at the top. We also need a new method which returns the element at the top to cover this feature:
/**
* Returns item at front of queue without removing.
* #return item at front
* #throws java.util.NoSuchElementException if empty
*/
public E top()
{
if (this.isEmpty())
{
throw new NoSuchElementException("Queue underflow");
}
return elements[size-1];
}
This was just an example. You might have more methods to change in your class to make it immutable.
If your stack is immutable, then by definition it cannot be changed. The push() and pop() methods cannot be completed.
When a method cannot be completed successfully, you can throw an exception. When a method can never be completed successfully, the standard exception to throw is UnsupportedOperationException.
For example:
public E[] push (E e) {
throw new UnsupportedOperationException();
}
EDIT:
You note in a comment that your push() method is just returning a deep copy of the stack with the new element. It looks like you're representing the immutable stack as an instance of a class, and the pushed stack as an array.
You can get the size of one of the two arrays referenced by newElements with newElements.length. So you could write code like this:
public E[] push (E e) {
E[] newElements=getNewElements();
int oldLength = newElements.length;
newElements=ensureCapacity(newElements);
int lastIndexInNewArray = oldLength;
newElements[ lastIndexInNewArray ] = e;
return newElements;
}
Below is an implementation of immutable stack in C#.
Pushing and popping give you back an entirely new stack, and Peek lets you look at the top of the stack without popping it.
Note that copying the entire stack is not necessary.
That is how immutable structures are implemented in any nontrivial cases. Nontrivial immutable structures are very useful in certain cases. Posters saying that this cannot be done are much misinformed.
The original code and more information can be found here:
https://blogs.msdn.microsoft.com/ericlippert/2007/12/04/immutability-in-c-part-two-a-simple-immutable-stack/
public interface IStack<T> : IEnumerable<T>
{
IStack<T> Push(T value);
IStack<T> Pop();
T Peek();
bool IsEmpty { get; }
}
public sealed class Stack<T> : IStack<T>
{
private sealed class EmptyStack : IStack<T>
{
public bool IsEmpty { get { return true; } }
public T Peek() { throw new Exception("Empty stack"); }
public IStack<T> Push(T value) { return new Stack<T>(value, this); }
public IStack<T> Pop() { throw new Exception("Empty stack"); }
public IEnumerator<T> GetEnumerator() { yield break; }
IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
}
private static readonly EmptyStack empty = new EmptyStack();
public static IStack<T> Empty { get { return empty; } }
private readonly T head;
private readonly IStack<T> tail;
private Stack(T head, IStack<T> tail)
{
this.head = head;
this.tail = tail;
}
public bool IsEmpty { get { return false; } }
public T Peek() { return head; }
public IStack<T> Pop() { return tail; }
public IStack<T> Push(T value) { return new Stack<T>(value, this); }
public IEnumerator<T> GetEnumerator()
{
for(IStack<T> stack = this; !stack.IsEmpty ; stack = stack.Pop())
yield return stack.Peek();
}
IEnumerator IEnumerable.GetEnumerator() {return this.GetEnumerator();}
}
Related
we are trying to submit a node using the integrated extension function. The node looks correct as far as it goes, but we can't access the individual elements, because there is always an outOfBound exception appearance.
How can we access the individual elements below the root element?
public ExtensionFunction updateTempNode = new ExtensionFunction() {
public QName getName() {
return new QName("de.dkl.dymoServer.util.ExternalFunctions", "updateTempNode");
}
public SequenceType getResultType() {
return SequenceType.makeSequenceType(
ItemType.BOOLEAN, OccurrenceIndicator.ONE
);
}
public net.sf.saxon.s9api.SequenceType[] getArgumentTypes() {
return new SequenceType[]{
SequenceType.makeSequenceType(
ItemType.STRING, OccurrenceIndicator.ONE),
SequenceType.makeSequenceType(
ItemType.DOCUMENT_NODE, OccurrenceIndicator.ONE)};
}
public XdmValue call(XdmValue[] arguments) {
String sessionId = arguments[0].itemAt(0).getStringValue();
SaplingElement tempNode = TransformationService.tempNodes.get(sessionId);
ItemTypeFactory itemTypeFactory = new ItemTypeFactory(((XdmNode) arguments[1]).getProcessor());
tempNode.withChild(
arguments[1].stream().map(xdmValue -> Saplings.elem(xdmValue.getStringValue()).withText(xdmValue.itemAt(0).getStringValue())).toList()
.toArray(SaplingElement[]::new)
);
System.out.println(tempNode);
return new XdmAtomicValue(true);
}
};
AOOB as I try to iterate
Data expected as document_node
Wild guess is that you want something like
tempNode = tempNode.withChild(
arguments[1]
.select(Steps.child().then(Steps.child()))
.map(childNode -> Saplings.elem(childNode.getNodeName()).withText(childNode.itemAt(0).getStringValue()))
.collect(Collectors.toList())
.toArray(new SaplingElement[]{})
);
which would populate tempNode with copies of the child nodes of the root element of the document node that is arguments[1]. There might be better ways to do that.
.
I'm investigating an issue with Esper 5.5.0. In the code base which I'm working on, an "INSERT INTO" statement is used and it pulls out data with EPStatement#iterator() from the "INSERT INTO" statement. It does return a non-empty Iterator (which looks weird to me though).
The issue is that the Iterator keeps accumulating data and never gets cleaned up. I'm trying to find a way to clean up the data in the Iterator but I don't know how I can do that. Its remove() method throws an Exception and deleting data from the derived window doesn't have any effect on the EPStatement object which corresponds to the "INSERT INTO" statement. How can I clean up the data in the Iterator which corresponds to the "INSERT INTO" statement? (EDIT: Not the one corresponds to the derived window, the one for the "INSERT INTO" statement itself)
Unfortunately I'm even unable to create a simple reproducer. They do something like the following but the Iterator is always empty when I try to replicate that behavior in new code. I would also like to know what is missing to replicate the behavior.
public class MyTest {
#Test
void eplStatementReturningNonEmptyIterator() {
EPServiceProvider engine = EPServiceProviderManager.getDefaultProvider();
EPRuntime rt = engine.getEPRuntime();
EPAdministrator adm = engine.getEPAdministrator();
adm.getConfiguration().addEventType(PersonEvent.class);
adm.createEPL("create window PersonEventWindow.win:keepall() as PersonEvent");
EPStatement epl = adm.createEPL("insert into PersonEventWindow select irstream * from PersonEvent");
rt.sendEvent(new PersonEvent("foo", 1));
rt.sendEvent(new PersonEvent("bar", 2));
// passes, but this question is not about this one
assert count(rt.executeQuery("select * from PersonEventWindow").iterator()) == 2;
// This question is about this one, I want to clean up the Iterator which epl.iterator() returns
assert count(epl.iterator()) == 2;
// (this assertion ^ fails actually; I cannot even replicate the issue)
}
private static int count(Iterator<?> it) {
int count = 0;
while (it.hasNext()) {
it.next();
count++;
}
return count;
}
public static class PersonEvent {
private String name;
private int age;
public PersonEvent(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
}
This code creates named window PersonEventWindow#keepall that keeps all events that ever arrived (its what keepall means). The code executes a fire-and=forget query rt.executeQuery that selects all events from the named window and the iterator returned provides each event. Iterators I don't think allow remove. One option, use a time window that automatically removes data from the named window like for example PersonEventWindow#time(10) which keeps only the last 10 seconds. Another option, execute a fire-and-forget query like rt.executeQuery("delete from PersonEventWindow") and that deletes all events from the named window.
It turned out that the Iterator for "insert into..." returns elements if it selects from a window. In order to clean up the Iterator, we can delete data from the window which the "insert into" query selects data from.
The following code verifies my explanation I believe:
public class MyTest3 {
EPServiceProvider engine;
EPAdministrator epa;
EPRuntime epr;
#BeforeEach
void setUp() {
engine = EPServiceProviderManager.getDefaultProvider();
epa = engine.getEPAdministrator();
epr = engine.getEPRuntime();
}
#Test
#DisplayName("The Iterator gets cleaned up by delete from MyWindow")
void cleanUpIterator() {
epa.getConfiguration().addEventType(MyEvent.class);
epa.createEPL("create window MyWindow.std:unique(id) as MyEvent");
epa.createEPL("insert into MyWindow select id from MyEvent");
epr.sendEvent(new MyEvent(1));
epr.sendEvent(new MyEvent(2));
EPStatement insertIntoAnotherWindow = epa.createEPL("insert into AnotherWindow select id from MyWindow");
assertThat(count(insertIntoAnotherWindow.iterator())).isEqualTo(2); // this returns the events surprisingly
epr.executeQuery("delete from MyWindow");
assertThat(count(insertIntoAnotherWindow.iterator())).isEqualTo(0); // now it's empty
}
public static class MyEvent {
private final int id;
public MyEvent(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
#AfterEach
void tearDown() {
engine.destroy();
}
private static int count(Iterator<?> it) {
int count = 0;
while (it.hasNext()) {
it.next();
count++;
}
return count;
}
}
The ExtendedDataModel from ajax4jsf uses a method called walk, looking like this:
public void walk(FacesContext ctx, DataVisitor dv, Range range, Object argument){}
This method is called several times in my application. Some topics on internet seem to say that it the latter is defined by the rows="x" in the xhtml. However, for me range is always defined as 0 (firstRow) - -1 (getRows).
So I was wondering where this range is defined, so I can figure out why the wrong parameters are passed to it. Debugging and googling hasn't helped me so far.
Range represents visible part of data displayed in table. If you have paginator, then paginator display which page (= from which row to which row) data is presented.
Problem can be in incorrect value of rows attribute of data table (for example rows attribute is missing).
Other place can be in incorrect implementation of data model. Object of data model class can be used as storage for data displayed in rich:dataTable.
Real example:
public class VSDataModel<RecordType> extends ExtendedDataModel<RecordType> implements Arrangeable {
private final FetchList<RecordType> list;
#Override
public void walk(FacesContext ctx, DataVisitor visitor, Range range, Object obj) {
try {
int firstRow = ((SequenceRange) range).getFirstRow();
int numberOfRows = ((SequenceRange) range).getRows();
if(list == null) {
throw new RuntimeException("Underlying list is null!");
}
if(list.getList() == null || firstRow != list.getFirstRow()) {
list.fetch(firstRow, numberOfRows);
}
for (RecordType elem : list.getList()) {
visitor.process(ctx, list.getPK(elem), obj);
}
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
It is used in Java private VSDataModel<Record> dependentList; and html
<rich:dataTable value="#{bean.dependentList}" rows="#{referenceData.recordsPerPage}">
so I was asked this question:
Consider the ADT stack. In addition to the operations Push, Pop
and Top, we want to support a new operation FindMin, which returns the smallest
element in the stack. Design the data structure and algorithms to support these
operations such that each of the four operations (Push, Pop, Top and FindMin) takes
constant time. No need to check the over and under conditions and no need
to give the procedures for Empty and Full. [Hint: use an extra stack.]
So I have seen some answers but they all seemed to take O(n) time once the FindMin function is used. And I don't really get what the hint is trying to tell me...Please help me!!! Thankssss!!
import java.util.Stack;
public class StackWithMin extends Stack<Integer> {
private Stack<Integer> minStack;
public StackWithMin () {
minStack = new Stack<Integer>();
}
public void push(int value){
if (value <= min()) { // Note the '=' sign here
minStack.push(value);
}
super.push(value);
}
public Integer pop() {
int value = super.pop();
if (value == min()) {
minStack.pop();
}
return value;
}
public int min() {
if (minStack.isEmpty()) {
return Integer.MAX_VALUE;
} else {
return minStack.peek();
}
}
public static void main(String args[]) {
StackWithMin stackWithMin = new StackWithMin();
stackWithMin.push(7);
stackWithMin.push(5);
stackWithMin.push(6);
stackWithMin.push(7);
stackWithMin.push(4);
System.out.println(stackWithMin.min());
stackWithMin.pop();
System.out.println(stackWithMin.min());
}
}
I'm rolling my own ActivatableCollection<T> for db4o but cribbing heavily from the builtin ActivatableList<T> implementation. I'm running into the problem where transparent persistence doesn't seem to be working correctly. In the test code below:
[Fact]
void CanStoreActivatableCollection()
{
var planets = new ActivatableCollection<Planet>();
var pagingMemoryStorage = new PagingMemoryStorage();
var config = Db4oEmbedded.NewConfiguration();
config.Common.Add(new TransparentActivationSupport());
config.Common.Add(new TransparentPersistenceSupport());
config.File.Storage = pagingMemoryStorage;
var objectContainer = Db4oEmbedded.OpenFile(config, "Memory.yap");
planets.Add(new Planet("Mercury"));
objectContainer.Store(planets);
planets.Add(new Planet("Venus"));
planets.Add(new Planet("Earth"));
objectContainer.Commit();
objectContainer.Close();
config = Db4oEmbedded.NewConfiguration();
config.Common.Add(new TransparentActivationSupport());
config.Common.Add(new TransparentPersistenceSupport());
config.File.Storage = pagingMemoryStorage;
objectContainer = Db4oEmbedded.OpenFile(config, "Memory.yap");
planets = objectContainer.Query<ActivatableCollection<Planet>>().FirstOrDefault();
Assert.NotNull(planets);
Assert.Equal(3, planets.Count);
objectContainer.Close();
}
The planet "Mercury" is stored, but not "Venus" and "Earth". If I change from ActivatableCollection to ActivatableList, then all 3 planets are stored.
What am I missing? My ActivatableCollection is just minimal implementation of ActivatableList as best as I can tell.
Below is my implementation of ActivatableCollection:
public class ActivatableCollection<T>
: ICollection<T>
, IActivatable
, INotifyCollectionChanged
{
List<T> _list;
List<T> List
{
get
{
if (_list == null)
_list = new List<T>();
return _list;
}
}
public ActivatableCollection()
{
}
public int Count
{
get
{
ActivateForRead();
return List.Count;
}
}
public bool IsReadOnly
{
get
{
ActivateForRead();
return ((IList) List).IsReadOnly;
}
}
public void Add(T t)
{
ActivateForWrite();
List.Add(t);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, t));
}
public void Clear()
{
ActivateForWrite();
List.Clear();
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public bool Contains(T t)
{
ActivateForRead();
return List.Contains(t);
}
public void CopyTo(T[] array, int index)
{
ActivateForRead();
List.CopyTo(array, index);
}
public IEnumerator<T> GetEnumerator()
{
ActivateForRead();
return List.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public bool Remove(T t)
{
ActivateForWrite();
bool removed = List.Remove(t);
if (removed)
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, t));
return removed;
}
[Transient]
private IActivator _activator;
public virtual void Bind(IActivator activator)
{
if (_activator == activator)
return;
if (activator != null && _activator != null)
throw new InvalidOperationException();
_activator = activator;
}
public virtual void Activate(ActivationPurpose purpose)
{
if (_activator == null)
return;
_activator.Activate(purpose);
}
protected virtual void ActivateForRead()
{
Activate(ActivationPurpose.Read);
}
protected virtual void ActivateForWrite()
{
Activate(ActivationPurpose.Write);
}
[Transient]
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged != null)
CollectionChanged(this, e);
}
}
I've also tried copying the code from GenericTypeHandlerPredicate and registering my ActivatableCollection to use the GenericCollectionTypeHandler. That results in a crash in GenericTypeFor() throwing an InvalidOperationException() when "Mercury" is being stored.
Just want to mention my answers from the db4o forums also here, for people with a similar problem:
First part of the issue:
From db4o's point of view nothing has changed in the 'ActivatableCollection' object and therefore no changes are stored. This is what is happening:
When you add the items, the ActivatableCollection is marked as changed.
When you commit the changes are stored. However the ' ActivatableCollection' holds the reference to the same object. db4o only stores the changes in the ActivatableCollection-object, which is the reference to the List. Since it is the same, no actual change is stored.
The List of the ActivatableCollection is never updated, because it wasn't marked as 'changed'
So the transparent activation doesn't see the changes in the list. You can fix your issue simply by using an ActivatableList in you're ActivatableCollection implementation. Just change the List with a IList interface and instantiate a ActivatableList instead of an List.
The second part of the issue: Why doesn't it work even when registering the GenericCollectionTypeHandler for this type? Here we hit a implementation detail. The GenericCollectionTypeHandler has an internal list of supported types, which doesn't include the self made 'ActivatableCollection'. GenericCollectionTypeHandler is not really part of the public API and intendet for internal use only.
Workaround / Fix
Just use an ActivatableList<T> instead of a List<T>. then everything works fine.