Recursive method in composite pattern - java

Hi i have a components class which can contain components and composite and i am writing a method to calculate the sum total of all the tax in its components.This class is part of a composite pattern code.The problem is my method which is recursive is not working properly i am having a stack overflow but for testing my method i only have two objects in my array list.
public class Nobles extends RiruritaniaSubjects
{
ArrayList vassalsanddukes = new ArrayList();
public void calculateTaxDueByComponents(){
Iterator iterator = vassalsanddukes.iterator();
while(iterator.hasNext()){
RiruritaniaSubjects vassalandduke=(RiruritaniaSubjects) iterator.next();
totalTaxdue+=vassalandduke.getTaxDue();
calculateTaxDueByComponents();
}
}
}
RiruritaniaSubjects is an abstract class and i have my other composite class extend it.I have edited the code and the stack overflow has stopped but my other problem is it seems to not add on the tax due if a component contains a component.
public void calculateTaxDueByComponents(){
Iterator iterator = vassalsanddukes.iterator();
while(iterator.hasNext()){
RiruritaniaSubjects vassalandduke=(RiruritaniaSubjects) iterator.next();
totalTaxdue+=vassalandduke.getTaxDue();
vassalandduke.calculateTaxDueByComponents();
}
}
I have decided to post snippets of different parts of my code.The problem i am having now is for e.g i have a noble A then a noble b , then a noble c.If i add noble c to noble b b.add(C). and i add b to a,a.add(B), my calculate Totaltaxdue() is not updating my tax due with the inner noble c.
public class Nobles extends RiruritaniaSubjects {
ArrayList vassalsanddukes = new ArrayList();
public void calculateTaxDueByComponents(){
Iterator iterator = vassalsanddukes.iterator();
while(iterator.hasNext()){
RiruritaniaSubjects vassalandduke=(RiruritaniaSubjects) iterator.next();
totalTaxdue+=vassalandduke.getTaxDue();
System.out.println(vassalandduke.getTaxDue());
vassalandduke.calculateTaxDueByComponents();
}
}
public double getTotalTaxDue(){
calculateTaxDueByComponents();
return totalTaxdue;
}
public class Prince {
Land land;
ArrayList allprinceSubjects = new ArrayList();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
RiruritaniaSubjects allsubjects = new Nobles();
RiruritaniaSubjects allsubject3 = new Nobles();
RiruritaniaSubjects allsubject4 = new Nobles();
allsubject4.add(allsubject3, 10);
allsubjects.add(allsubject4, 10);
System.out.println(allsubjects.getTotalTaxDue());
}
}
By my own workings the output should be 7 because it should be 3.5 for each noble but i am getting 3.5 as the output which is wrong.

You're calling the calculateTaxDueByComponents method on this rather than to call it on your subcomponents.
Moreover, the calculateTaxDueByComponents is a void method. It doesn't return anything. So it's impossible to add its result (since it doesn't have any) to the tax due by the current component. Your method should probably look like this:
public int calculateTaxDueByComponents() {
int taxDueByThisComponent = getTaxDue();
int taxDueByThisComponentAndAllItsSubComponentsRecursively = taxDueByThisComponent;
Iterator iterator = vassalsanddukes.iterator();
while(iterator.hasNext()){
RiruritaniaSubjects vassalandduke=(RiruritaniaSubjects) iterator.next();
taxDueByThisComponentAndAllItsSubComponentsRecursively += vassalandduke.calculateTaxDueByComponents();
}
return taxDueByThisComponentAndAllItsSubComponentsRecursively;
}
Side note: your code would be more readable and more type-safe if you used generic collections: List<RiruritaniaSubjects> rather than List.

You are calling the method from with the method, leading to an infinite loop! Just remove that call:
public void calculateTaxDueByComponents(){
Iterator iterator = vassalsanddukes.iterator();
while(iterator.hasNext()){
RiruritaniaSubjects vassalandduke=(RiruritaniaSubjects) iterator.next();
totalTaxdue+=vassalandduke.getTaxDue();
// calculateTaxDueByComponents(); DON't DO THIS!
}
}

I will assume that calculateTaxDueByComponents belongs to RirutaniaSubjects.
You are certainly going to have a stack overflow because you are calling it on this. Probably you want to do:
public void calculateTaxDueByComponents(){
Iterator iterator = vassalsanddukes.iterator();
int totalTaxDue = getTaxDue();
while(iterator.hasNext()){
RiruritaniaSubjects vassalandduke=(RiruritaniaSubjects) iterator.next();
totalTaxdue+=vassalandduke.calculateTaxDueByComponents();
}
}

Related

Iterator in reverse - for reduceRight functionality

Trying to implement some reduceRight functionality.
For performance would be nice to iterate from right to left, without reversing everything first, and then going left to right. Normally we do:
Iteratable iterable ...;
Iterator iterator = iterable.iterator();
iterator.next();
but I am looking for something like:
Iteratable iterable ...;
Iterator iterator = iterable.reverseIterator();
iterator.next();
I see this solution: Iterating through a list in reverse order in java
The current accepted answer says that this works:
ArrayList<...> a = new ArrayList<...>();
// Add elements to list.
// Generate an iterator. Start just after the last element.
ListIterator li = a.listIterator(a.size());
// Iterate in reverse.
while(li.hasPrevious()) {
System.out.println(li.previous());
}
Anyone know how to implement reverse iteration given only an Iterable in hand? I don't have an ArrayList or List in hand, I have an Iterable in hand. I suppose I can convert the Iterable to an ArrayList, reverse the list, then get an iterator, but that would be no fun :)
Simple answer: not possible in a generic performant way.
The essence of iterator is to get you one direction, not both. And imagine a singlely linked list. That thing really has "only one direction"!
So the question how you can reverse an iterable thingy really requires you to look at the exact implementation.
Without that possibility, you have to use an intermediate data structure to fetch all entries before reversing.
You'll have to iterate over the original Iterator once in order to construct a reversed Iterator (assuming your original Iterator is finite).
For example:
static <T> Iterator<T> getReversedIterator(Iterable<T> iterable) {
Iterator<T> iter = iterable.iterator();
List<T> rev = new ArrayList<>();
while (iter.hasNext()) {
rev.add (0, iter.next());
}
return rev.iterator();
}
If you have an Iterable in hand, as you wrote in your question, then someone provided you with it. I would suggest asking the provider to supply an Iterable that supports reverse iteration.
Here is how I do it. If you are using a for loop, this will cause the original Iterator to be completely consumed and a new linked list to be created before the first iteration. This can obviously be an issue with large iterables, but it is predictable and easy to use. It has the advantage of working with anything that implements Iterable vs. some solutions that only work with specific types.
import java.util.Iterator;
public class Reversible<E> implements Iterable<E> {
private Iterable<E> source;
public Reversible(Iterable<E> source) {
this.source = source;
}
public Iterator<E> iterator() {
return new Reverserator<>(source.iterator());
}
public static class Reverserator<E> implements Iterator<E> {
private Entry<E> next = null;
private Reverserator(Iterator<E> source) {
while (source.hasNext()) {
next = new Entry<>(source.next(), next);
}
}
public boolean hasNext() {
return next != null;
}
public E next() {
Entry<E> curr = next;
next = curr.next;
return curr.obj;
}
private static class Entry<E> {
private E obj;
private Entry<E> next;
private Entry(E obj, Entry<E> next) {
this.obj = obj;
this.next = next;
}
}
}
}
It is quite simple to use:
List<String> names = new ArrayList<>();
names.add("George");
names.add("Fred");
names.add("Harry");
for (String name:new Reversible<>(names)) {
System.out.println(name);
}
Returns:
Harry
Fred
George

Enumeration is throwing concurrentModification Exception. why?

Enumeration is Fail-safe. Fail-safe iterators will work on the cloning of the original collection. then why it is throwing concurrentModificationException? please clarify.
Please find my code:
public static void main(String[] args) {
Vector<String> v=new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Enumeration en=(Enumeration) Collections.enumeration(v);
while(en.hasMoreElements())
{
String value=(String) en.nextElement();
System.out.println(value);
v.remove(value);//modifying the collection
}
}
Find the error message below
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.Vector$Itr.checkForComodification(Unknown Source)
at java.util.Vector$Itr.next(Unknown Source)
at java.util.Collections$2.nextElement(Unknown Source)
at valar.org.src.EnumerationTest.main(EnumerationTest.java:24)
Collections.enumeration(Collection) will create an iterator from the collection passed as parameter :
public static <T> Enumeration<T> enumeration(final Collection<T> c) {
return new Enumeration<T>() {
private final Iterator<T> i = c.iterator();
public boolean hasMoreElements() {
return i.hasNext();
}
public T nextElement() {
return i.next();
}
};
}
It means that the iterator is backed to the collection which you remove element in the iterator loop and you cannot remove an element of the collection on which you iterate with the iterator.
You should create a copy of the Vector you pass in the enumeration() invocation :
Enumeration<String> en = Collections.enumeration(new Vector<String>(v));
And as a side note, you should favor List interface and ArrayList implementation over Vector (that is synchronized) and declare generics collection that spares cast and increase the type safety of the code.
So it would give this code (I left the Vector use as it is maybe a not modifiable constraint but I specified the generics as it is often simpler to add even in a legacy code):
Vector<String> v = new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Enumeration<String> en = Collections.enumeration(new Vector<String>(v));
while (en.hasMoreElements()) {
String value = (String) en.nextElement();
System.out.println(value);
v.remove(value);// modifying the collection
}
Your Enumeration uses an Iterator internally. While iterating over the elements, you can't use the vector itself to remove items. You have to use the iterator. But you don't have access to it. Create an iterator instead:
public static void main(String[] args) {
final Vector<String> v = new Vector<String>();
v.add("Amit");
v.add("Raj");
// Use an Iterator to remove the value you are iterating over
final Iterator<String> iterator = v.iterator();
while (iterator.hasNext()) {
final String value = iterator.next();
System.out.println(value);
iterator.remove();
}
}
Though Vector is practically deprecated anyways. You should propably use a List instead:
The imports for the correct Lists (don't use the awt.List for this):
import java.util.ArrayList;
import java.util.List;
The changed code:
public static void main(String[] args) {
final List<String> v = new ArrayList<>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
final Iterator<String> iterator = v.iterator();
while (iterator.hasNext()) {
final String value = iterator.next();
System.out.println(value);
iterator.remove();
}
}
Also note you can use the interface as Type which is generally preferred to using the implementation.
Edit:
Looking at your example, maybe what you really need is a queue:
public static void main(String[] args) {
final Queue<String> v = new LinkedList<>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
System.out.println("Size: " + v.size());
for (String element = v.poll(); element != null; element = v.poll()) {
System.out.println(element);
}
System.out.println("Size: " + v.size());
}
Output:
Size: 3
Amit
Raj
Pathak
Size: 0
This works the same as your example. For more info on Collections see The official Collections Java Trail
Enumeration is Fail-safe.
Correct. (Allowing for some language difficulties.)
Fail-safe iterators will work on the cloning of the original collection.
Correct. (Allowing for some language difficulties.)
then why it is throwing concurrentModificationException?
Because there is no cloning involved.
Where is the cloning?
You are using Enumeration which is not supported removed method.Once you created a Enumeration then it test for checkForComodification .so when you do the remove from vector the modCount increases and expectedModCount not modified.
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
please modify your code using iterator
public static void main(String[] args) {
Vector<String> v = new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Iterator<String> it =v.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println(value);
it.remove();
}
}

ConcurrentModificationException persisting even with ListIterator

I'm doing a library system on Java. I have a class called Things with two children: Print and Digital. Print is then divided into Book and Periodical.
The following is a snippet of the code I wrote to print items. The full code has imports.
public class Collection
{
private ArrayList <Things> theCollection;
private ListIterator <Things> listItr;
public Collection ()
{
theCollection = new ArrayList <> ();
listItr = theCollection.listIterator ();
}
public void get ()
{
Things sThing;
Book sBook;
Periodical sPeriodical;
Digital sDigital;
sThing = listItr.next ();
if (sThing instanceof Book)
{
sBook = (Book) sThing;
sBook.bookInfo ();
}
else if (sThing instanceof Periodical)
{
sPeriodical = (Periodical) sThing;
sPeriodical.periodicalInfo ();
}
else if (sThing instanceof Digital)
{
sDigital = (Digital) sThing;
sDigital.digitalInfo ();
}
}
public void printAll ()
{
while (listItr.hasNext ())
get ();
}
}
I have a problem on the following statement in the get() method:
sThing = listItr.next ();
When I ran the code, it gave me a ConcurrentModificationException. I tried to search for answers online, but all of them suggested to use an iterator, and I have that. Where did I do wrong?
Thanks for your help.
The problem
You create/request an iterator while constructing your class, directly after creating the list. At this point the list will be empty.
I assume that you afterwards add/remove elements to/from that list. This is a concurrent modification because the iterator constrains the iteration to happen on an unmodified list after its creation. The next call to the iterator will then throw this exception.
The solution
Don't create the iterator in the constructor of your class. Create it at the needed time:
public class Collection {
private ArrayList <Things> theCollection;
public Collection () {
theCollection = new ArrayList <> ();
}
public void get () {
...
ListIterator <Things> listItr = theCollection.listIterator();
sThing = listItr.next ();
...
}
}
the problem lies in the constructor:
public Collection ()
{
theCollection = new ArrayList <> ();
listItr = theCollection.listIterator ();
}
you are creating a ListIterator before adding elements to the list; in order to avoid the error you must create the iterator just before iterating over the elements; so remove the iterator creation in the conustructor and place in just before you need it; see here and here for similar questions.

Removing the contents of an arraylist of customized object type based on a specific comparison between the elements of the arraylist

I have an ArrayList of type RemoveTest, where RemoveTest is a user defined class.
RemoveTest has two properties of String type mId and rmId.
I need to find in the ArrayList, elements(Objects of type RemoveTest) satisfying the below criteria: such that the value of obj1.rmId() is same as obj2.getmId() and then remove both of these elements(obj1 and obj2).
I tried this by writing the below code:
import java.util.ArrayList;
import java.util.Iterator;
public class RemoveItr {
public static void main(String[] args){
ArrayList<RemoveTest> eleList = new ArrayList<RemoveTest>();
RemoveTest obj1 = new RemoveTest();
obj1.setmId("m1");
obj1.setRmId("");
RemoveTest obj2 = new RemoveTest();
obj2.setmId("m2");
obj2.setRmId("m1");
RemoveTest obj3 = new RemoveTest();
obj3.setmId("m3");
obj3.setRmId("");
RemoveTest obj4 = new RemoveTest();
obj4.setmId("m4");
obj4.setRmId("m3");
RemoveTest obj5 = new RemoveTest();
obj5.setmId("m5");
obj5.setRmId("");
eleList.add(obj1);
eleList.add(obj2);
eleList.add(obj3);
eleList.add(obj4);
eleList.add(obj5);
Iterator<RemoveTest> i = eleList.iterator();
while(i.hasNext()){
RemoveTest fwdM =(RemoveTest)i.next();
String fwdId = fwdM.getmId();
Iterator<RemoveTest> ni = eleList.iterator();
while(ni.hasNext()){
RemoveTest revM =(RemoveTest)ni.next();
String revId = revM.getRmId();
if(fwdId.equals(revId)){
System.out.println("fwdId "+fwdId+"- revId "+revId);
i.remove();
ni.remove();
}
}
}
}
}
public class RemoveTest {
String mId;
String rmId;
public String getmId() {
return mId;
}
public void setmId(String mId) {
this.mId = mId;
}
public String getRmId() {
return rmId;
}
public void setRmId(String rmId) {
this.rmId = rmId;
}
}
Note: both classes are Public as they were not in the same source file.
But, I got ConcurrentModificationException and I believe it is because, that as I was already in the middle of iterating through the arraylist, and then other loop(iterator) steps in and tries to operate on the same ArrayList.
Is this understanding correct? and If so, how can I resolve this problem and achieve the solution.
You can't modify a collection while iterating over it, except by using Iterator.remove().
This rule implies that you can't use two iterators simultaneously and expect remove() to work, because calling remove() on one iterator will violate the rule for the other iterator.
The solution is to collect all the entries that need deleting in a separate Set, then after your logic has completed, call List.removeAll(set).
Given this, you don't need iterators at all - just use the foreach syntax:
For a simplistic example:
List<RemoveTest> list = new ArrayList<RemoveTest>();
// populate list
Set<RemoveTest> removals = new HashSet<RemoveTest>();
for (RemoveTest i : list)
for (RemoveTest j : list)
if (...)
removals.add(i); // j will get added in another iteration
list.removeAll(removals);
Use CopyOnWriteArrayList instead of ArrayList, it should solve your problem.

What is the optimal way to transverse a TreeSet from last node to first in java?

I already have a solution to traverse a TreeSet. My question is related to performance, is the way I implemented the optimal one? See my code example below.
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add("F");
ts.add("B");
ts.add("H");
ts.add("Z");
while (!ts.isEmpty())
{
String last = (String)ts.last();
System.out.println(last);
ts.remove(last);
}
// OUTPUT: Z H F B
}
Seems simple
TreeSet ts = new TreeSet();
Iterator i = ts.descendingIterator();
while(i.hasNext()) {
Object next = i.next();
}
or
for(Object e : ts.descendingSet()) {
}
for Java below 1.6 you can try
TreeSet tmp = new TreeSet(Collections.reverseOrder());
tmp.addAll(ts);
for(Object e : tmp) {
}
A JDK 5 compatible way: create a new new collection with the comparator reversed.
TreeSet<String> trev = new TreeSet<String>(Collections.reverseOrder());
trev.addAll(ts);
//now you can just iterate which the usual forward iterator.
Iterator i = trev.iterator();
while(i.hasNext()) {
String next = i.next();
}

Categories