Iterable & Iterator Implementation Issue (JAVA) - java

I am new to Java and I am trying to learn about the implementation of Iterable & Iterator.
import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;
public class ClassMates implements Iterable{
private String className;
private LinkedList<String> nameList;
public ClassMates(String className){
this.className = className;
this.nameList = new LinkedList<String>();
}
public void addName(String name){
nameList.add(name);
}
public LinkedList<String> getNameList() {
return nameList;
}
#Override
public Iterator<String> iterator() {
return new IteratorClass();
}
// Inner Class
private class IteratorClass implements Iterator<String>{
private int index;
public IteratorClass(){
this.index = 0;
}
#Override
public boolean hasNext() {
return index < nameList.size();
}
#Override
public String next() {
if(hasNext()){
int i = index;
index++;
System.out.println("This is "+ i);
return nameList.get(i);
}
throw new NoSuchElementException();
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}
My question is: when I finish the implementation and try to apply the for-each to the "iterable" object, the compiler said types are not match.
Here is the main() execution for apply for-each:
public class Main {
public static void main(String[] args) {
ClassMates classMates = new ClassMates("03-01");
classMates.addName("Classmate 1");
classMates.addName("Classmate 2");
classMates.addName("Classmate 3");
classMates.addName("Classmate 4");
for(String name : classMates){
//HERE! the compiler report "String" is not match the return type of "classMates"
System.out.println(name);
}
}
Anyone can point me out the problem?
Thank you!!!

As your class will iterate through strings, you should specify the template type:
public class ClassMates implements Iterable<String>

Related

How to implement an interface for two classes with an iterator

I'm trying out Interfaces in java and I want to implement a common interface for a really simple stack, with pop() and push() methods and an iterator.
The problem is that I don't know how to specify the iterator in the interface. No matter which way I try, I get
Main.java:32: error: for-each not applicable to expression type
for (Integer i : ss)
^
required: array or java.lang.Iterable
found: Stack<Integer>
The code is as follows:
interface Stack<T> {
boolean push(T t);
boolean pop();
//Iterator<T> iterator(); // How to indicate it needs, and will have, an iterator?
}
public class DynamicStack<T> implements Iterable<T>, Stack<T>
{
// implementation-specific variables go here
public DynamicStack() {
//...
}
public boolean push(T t) {
//...
}
public boolean pop() {
//...
}
private class StackIterator implements Iterator<T> {
DynamicStack<T> stk;
//...
// Iterator constructor
private StackIterator(DynamicStack<T> stk)
{
//...
}
public boolean hasNext()
{
//...
}
public T next() throws NoSuchElementException
{
//...
}
public void remove() throws UnsupportedOperationException
{
throw new UnsupportedOperationException(); // I chose not to implement this one
}
}
// Iterator method
public Iterator<T> iterator()
{
return new StackIterator(this);
}
}
public class StaticStack<T> implements Iterable<T>, Stack<T>
{
// implementation-specific variables go here
public StaticStack()
{
//...
}
public boolean push(T t)
{
//...
}
public boolean pop()
{
//...
}
private class StackIterator implements Iterator<T>
{
StaticStack<T> stk;
//...
private StackIterator(StaticStack<T> stk)
{
//...
}
public boolean hasNext()
{
//...
}
public T next() throws NoSuchElementException
{
//...
}
public void remove() throws UnsupportedOperationException
{
//...
}
}
// Iterator method
public Iterator<T> iterator()
{
return new StackIterator(this);
}
}
Main simply does this, after creating a few stacks of each type and adding a few elements:
public static void showStuff(Stack<Integer> ss)
{
for (Integer i : ss)
System.out.print(i+" ");
System.out.println();
}
In your test class, you are operating against Stack interface, so that is the one that needs to conform to Iterable. In this case it doesn't help if StaticStack or DynamicStack implement it if Stack does not.
To get Stack to be able to be used as Iterable just change your Stack to extend Iterable:
public interface Stack<T> extends Iterable<T> {
boolean push(T t);
boolean pop();
}
and
public class StaticStack<T> implements Stack<T>
and the code runs just fine:
public class Tester {
public static void main(String args[]) {
Stack<Integer> ss = new StaticStack<>();
for (Integer i : ss)
System.out.print(i+" ");
System.out.println();
}
}
You need you class to implement Iterable<T>, which has the iterator() method, which returns Iterator<T>.

Enumeration interface. Default methods implementation

Good evening, consider the following:
public class TestEnum implements Enumeration<String> {
private Enumeration<String> files;
private TestEnum(Vector<String> files) {
this.files = files.elements();
}
public Enumeration<String> getFiles() {
return files;
}
#Override
public boolean hasMoreElements() {
return files.hasMoreElements();
}
#Override
public String nextElement() {
return files.nextElement();
}
public static void main(String[] args) {
Vector<String> vector = new Vector<>();
vector.add("1");
vector.add("2");
vector.add("3");
vector.add("4");
vector.add("5");
TestEnum obj = new TestEnum(vector);
while(obj.getFiles().hasMoreElements()) {
System.out.println(obj.getFiles().nextElement());
}
}
}
I don't understand, where is nextElement() and hasMoreElements() methods default implementation when operating whit enumeration of strings?
I know that methods implementation should be created on programmers own and it have been created , but in line:
return files.nextElement();
I call the method nextElement() on "files" object that has another implementation? If method has my implementation then it should be call nextElement() indefinitely? Or I'm wrong?
Sorry, guys, I have found it:
public Enumeration<E> elements() {
return new Enumeration<E>() {
int count = 0;
public boolean hasMoreElements() {
return count < elementCount;
}
public E nextElement() {
synchronized (Vector.this) {
if (count < elementCount) {
return elementData(count++);
}
}
throw new NoSuchElementException("Vector Enumeration");
}
};
}
In Vector class

How to implement extended apply method? Java

My question has to do with implementing the FlatApply class that I have created previously into this class called FilteringFlatApplyFunction. I cannot seem to implement the apply correctly because the static class continues to tell me it needs to be abstract and the #Override is not working the way it is supposed to. The end goal I am looking for is a way to use inheritance to borrow most of the functionality from the FlatApply class and implement the filter class. I have tried many different things but still can't get it, the predicate "pred" checks if the given predicate is true and if so, indicates to return the element, I thought that would implement FlatApply,I have been getting this error what seems like forever now. Thanks
Error:
FilteringFlatApplyFunction is not abstract and does not override abstract method apply(T) in FlatApplyFunction
where T is a type-variable:
T extends Object declared in class FilteringFlatApplyFunction
package iterators;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import iterators.Apply;
// Iterator that uses a Predicate to filter out elements from the input
public class Filter<T> extends FlatApply<T,T> {
public Filter(Predicate<T> p, Iterator<T> input) {
super(new FilteringFlatApplyFunction<T>(p),input);
}
// uses a Predicate to decide whether the input element is output or not
private static class FilteringFlatApplyFunction<T> implements FlatApplyFunction<T,T> {
private final Predicate pred;
public FilteringFlatApplyFunction(Predicate<T> p) {
this.pred = p;
}
#Override
public T apply(Iterator T) {
T result = null;
if((!T.hasNext())) throw new IllegalStateException();
if (pred.check(T.next()) == true){
result = (T) T.next();
}
else{
return (T) T;
}
}
Here is the FlatApply
package iterators;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class FlatApply<InT,OutT> implements Iterator<OutT> {
private final Iterator<InT> input;
private final FlatApplyFunction<InT,OutT> f;
private final Queue<OutT> q;
public FlatApply(FlatApplyFunction<InT,OutT> f, Iterator<InT> input) {
this.input = input;
this.f = f;
this.q = new LinkedList<OutT>();
}
#Override
public boolean hasNext() {
if (!q.isEmpty()) {
return true;
}
else {
while(q.isEmpty() && input.hasNext()) {
List<OutT> result = f.apply(input.next());
q.addAll(result);
}
if(q.isEmpty()) return false;
else return true;
}
}
#Override
public OutT next() {
if((!hasNext())) throw new IllegalStateException();
return q.poll();
}
}
Here is the FlatApplyFunction
package iterators;
import java.util.List;
public interface FlatApplyFunction<InT, OutT> {
public List<OutT> apply(InT x);
}
Here is the apply class
package iterators;
import java.util.Iterator;
public class Apply<InT,OutT> implements Iterator<OutT> {
// The function that will be applied to each input element to make an output element
private final ApplyFunction<InT,OutT> f;
// The Iterator that this Apply object will get its input from
private final Iterator<InT> input;
public Apply(ApplyFunction<InT, OutT> f, Iterator<InT> input) {
this.input = input;
this.f = f;
}
#Override
public boolean hasNext() {
return input.hasNext();
}
#Override
public OutT next() {
if((!hasNext())) throw new IllegalStateException();
OutT result = f.apply(input.next());
return result;
}
}
The FlatApplyFunction interface says this:
public List<OutT> apply(InT x);
But the FilteringFlatApplyFunction implementation of that interface says this:
public T apply(Iterator T) {
The interface requires a List to be returned, by you're just returning T. Also, the parameter is required to be a T, but you have it as an Iterator.
Make those match, and this compiler error should go away.

Extending abstract classes

MyMath's constructor is supposed to call Homework's constructor, but super(); returns an error 'cannot find symbol'. It should not have any arguments.
Also, I am confused about how to call the method createAssignment using an arraylist, but I have to use it. Any advice?
Homework
public abstract class Homework {
private int pagesToRead;
private String typeHomework;
public Homework(int pages, String hw) {
// initialise instance variables
pagesToRead = 0;
typeHomework = "none";
}
public abstract void createAssignment(int p);
public int getPages() {
return pagesToRead;
}
public void setPagesToRead(int p) {
pagesToRead = p;
}
public String getTypeHomework() {
return typeHomework;
}
public void setTypeHomework(String hw) {
typeHomework = hw;
}
}
MyMath
public class MyMath extends Homework {
private int pagesRead;
private String typeHomework;
public MyMath() {
super();
}
public void createAssignment(int p) {
setTypeHomework("Math");
setPagesToRead(p);
}
public String toString() {
return typeHomework + " - " + pagesRead;
}
}
public class testHomework {
public static void main(String[] args) {
ArrayList<Homework> list = new ArrayList<Homework>();
list.add(new MyMath(1));
list.add(new MyJava(1));
for (Homework s : list) {
s.createAssignment();
}
}
}
Compiler error:
Regarding the compiler error, you have to change the MyMath constractor to somthing like:
public MyMath() {
super(someInt, someString);
}
Or, you can add a non-arg constructor to the Homework class:
public Homework() {
this(someInt,someString);
}
You can learn about the super() keyword in the Javadocs tutoriel:
If a constructor does not explicitly invoke a superclass constructor,
the Java compiler automatically inserts a call to the no-argument
constructor of the superclass. If the super class does not have a
no-argument constructor, you will get a compile-time error. Object
does have such a constructor, so if Object is the only superclass,
there is no problem.
Code Suggestion:
As there is many other issues in your question, i modified all your classes like below:
Homework.java:
public abstract class Homework {
private int pagesToRead;
private String typeHomework;
{
// initialise instance variables
pagesToRead = 0;
typeHomework = "none";
}
public Homework(int pages, String hw) {
this.pagesToRead = pages;
this.typeHomework = hw;
}
public abstract void createAssignment(int p);
public int getPages() {
return pagesToRead;
}
public void setPagesToRead(int p) {
pagesToRead = p;
}
public String getTypeHomework() {
return typeHomework;
}
public void setTypeHomework(String hw) {
typeHomework = hw;
}
}
MyMath.java
public class MyMath extends Homework {
private int pagesRead;
private String typeHomework;
public MyMath(int pages, String hw) {
super(pages,hw);
}
public void createAssignment(int p) {
setTypeHomework("Math");
setPagesToRead(p);
}
public String toString() {
return typeHomework + " - " + pagesRead;
}
}
TestHomework.java:
class TestHomework {
public static void main(String[] args) {
ArrayList<Homework> list = new ArrayList<Homework>();
// will create a homework with type Math and one page to read
list.add(new MyMath(1,"Math"));
// Assuming MyJava is similar to MyMath
list.add(new MyJava(1,"Java"));
for (Homework s : list) {
if (s instanceof MyMath) {
// modify the number of pages to read for the Math homework
s.createAssignment(3);
} else if (s instanceof MyJava) {
// modify the number of pages to read for the Java homework
s.createAssignment(5);
} else {
s.createAssignment(7);
}
}
}
}

Decorator Design Pattern in Java - why it doesnt add new ingridients to list?

I tried to implement a simple Decorator Pattern in Java. The main idea is that a concrete decorator have to add something to the basic list. However, my implementation doesnt work correctly and I dont know why.
The output is as you see below:
ING -1,ING 0,ING 1.
but it should be:
ING -1,ING 0,ING 1, ING 2.
Heres my code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package newpackage;
import java.util.ArrayList;
import java.util.List;
abstract class Tester {
protected List<String> ingridients = new ArrayList();
protected String description;
public String getDescription() {
description = "";
for (String i : ingridients) {
description += i;
description += ",";
}
description = description.substring(0, description.length() - 1);
description += ".";
return description;
}
}
abstract class Decorator extends Tester {
#Override
public abstract String getDescription();
}
class Test1 extends Tester {
public Test1() {
this.ingridients.add("ING -1");
this.ingridients.add("ING 0");
}
}
class Ing1 extends Decorator {
private Tester t;
public Ing1(Tester t) {
this.t = t;
}
#Override
public String getDescription() {
this.t.ingridients.add("ING 1");
return this.t.getDescription();
}
}
class Ing2 extends Decorator {
private Tester t;
public Ing2(Tester t) {
this.t = t;
}
#Override
public String getDescription() {
this.t.ingridients.add("ING 2");
return this.t.getDescription();
}
}
public class Test {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Tester t = new Test1();
t = new Ing1(t);
t = new Ing2(t);
System.out.println(t.getDescription());
}
}
Edited code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package newpackage;
import java.util.ArrayList;
import java.util.List;
interface Tester {
List<String> ingridients = new ArrayList();
public String getDescription();
}
abstract class Decorator implements Tester {
#Override
public abstract String getDescription();
}
class Test1 implements Tester {
public Test1() {
ingridients.add("ING -1");
ingridients.add("ING 0");
}
#Override
public String getDescription() {
String description = "";
for (String i : ingridients) {
description += i;
description += ",";
}
description = description.substring(0, description.length() - 1);
description += ".";
return description;
}
}
class Ing1 extends Decorator {
private Tester t;
public Ing1(Tester t) {
this.t = t;
}
#Override
public String getDescription() {
this.t.ingridients.add("ING 1");
return this.t.getDescription();
}
}
class Ing2 extends Decorator {
private Tester t;
public Ing2(Tester t) {
this.t = t;
}
#Override
public String getDescription() {
this.t.ingridients.add("ING 2");
return this.t.getDescription();
}
}
public class Test {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Tester t = new Test1();
t = new Ing1(t);
t = new Ing2(t);
System.out.println(t.getDescription());
}
}
I run this in a debugger and I could see that your Decorators are not just decorators as they have state of their own. Make your Tester an interface and have you decorators only wrap the concrete instances and not have state of their own.
// adds to the list in t1
this.t.ingridients.add("ING 2");
// add to the list in t
this.t.ingridients.add("ING 1");
// returns the contents of t.
return this.t.getDescription();
At the end t.ingredients has three items, t1.ingredients has 1 element and t2.ingredients has none.
You could write it this way
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Test {
public static void main(String[] ignored) {
Tester t012 = new Ing2(new Ing1(new Ing0(new None())));
System.out.println(t012.getDescription());
Tester t210 = new Ing0(new Ing1(new Ing2(new None())));
System.out.println(t210.getDescription());
}
}
abstract class Tester {
public List<String> getIngredients() {
return Collections.emptyList();
}
public String getDescription() {
StringBuilder sb = new StringBuilder();
String sep = "";
for (String s : getIngredients()) {
sb.append(sep).append(s);
sep=", ";
}
sb.append(".");
return sb.toString();
}
}
class None extends Tester {
}
class Ing0 extends Tester {
private final Tester wrapped;
Ing0(Tester wrapped) {
this.wrapped = wrapped;
}
#Override
public List<String> getIngredients() {
List<String> list = new ArrayList<>(wrapped.getIngredients());
list.add("ING -1");
list.add("ING 0");
return Collections.unmodifiableList(list);
}
}
class Ing1 extends Tester {
private final Tester wrapped;
Ing1(Tester wrapped) {
this.wrapped = wrapped;
}
#Override
public List<String> getIngredients() {
List<String> list = new ArrayList<>(wrapped.getIngredients());
list.add("ING 1");
return Collections.unmodifiableList(list);
}
}
class Ing2 extends Tester {
private final Tester wrapped;
Ing2(Tester wrapped) {
this.wrapped = wrapped;
}
#Override
public List<String> getIngredients() {
List<String> list = new ArrayList<>(wrapped.getIngredients());
list.add("ING 2");
return Collections.unmodifiableList(list);
}
}
prints
ING -1, ING 0, ING 1, ING 2.
ING 2, ING 1, ING -1, ING 0.

Categories

Resources