I've this problem:
Given the iterable class Foo, which keeps always only one int
value which is set on its constructor, make an iterator so it
respects all of its restrictions which are: you can't change the int
value after its initialization. You should include only the required
exceptions to be thrown.
Ok, so far, if I understood the question the right way, I should create an iterator for that Foo class, however I've never done this before and it seems to be that the question itself is a bit misleading. Is it a list? Or shouldn't it be? Anyway, despite that, all I want to know is how to create it.
So now I've this:
public class Foo implements Iterable<Foo> {
#Override
public Iterator<Foo> iterator() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
But I don't even know if this is the right way to do so.
I'd be very appreciated if someone could help me out with this.
Thank you in advance.
A minimal example would be to return an empty iterator, whose hasNext() always returns false and next() will throw NoSuchElementException.
public Iterator<Foo> iterator() {
return new Iterator<Foo>() {
public boolean hasNext() {
return false;
}
public Foo next() {
throw new NoSuchElementException();
}
};
}
Of course most iterators have states. For example you can iterate from 0 to the integer value the Foo instance holds.
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Foo implements Iterable<Foo> {
private final int value;
public Foo(final int value) {
this.value = value;
}
#Override
public Iterator<Foo> iterator() {
return new Iterator<Foo>() {
private Foo foo = new Foo(0);
#Override
public boolean hasNext() {
return foo.value < Foo.this.value;
}
#Override
public Foo next() {
if (!hasNext()) throw new NoSuchElementException();
Foo cur = foo;
foo = new Foo(cur.value+1);
return cur;
}
};
}
public static void main(String[] args) {
Foo foo = new Foo(10);
for (Foo f: foo) {
System.out.println(f.value);
}
}
}
Related
I want to subclass Iterator into what I'll call FooIterator. My code looks something like this:
public class FooIterator<E> implements Iterator<E> {
public FooIterator(Collection<Bar> bars) {
innerIterator = bars.iterator();
}
#Override
public boolean hasNext() {
return innerIterator.hasNext();
}
#SuppressWarnings("unchecked")
#Override
public E next() {
Bar bar = innerIterator.next();
return new E(bar);
}
#Override
public void remove() {
throw new UnsupportedOperationException("Don't remove from FooIterator!");
}
private Iterator<Bar> innerIterator;
}
...except, of course, this doesn't work because I can't instantiate a new E from a Bar.
I would only ever use this with an E that has a constructor that takes a Bar. Is there any way to "prove" that to the compiler, or to just throw a runtime error if E doesn't have an appropriate constructor?
Or perhaps I'm just not using the right design pattern here? I've been doing a lot of C++ recently, and I feel like I might be approaching this the wrong way.
This is a somewhat convoluted approach but it could work and would be type safe (solutions using reflection won't). It basically consists in delegating the construction of an E from a Bar to a separate class. You could have a BarConverter interface:
interface BarConverter<E> {
E convert (Bar bar);
}
Then your class could become:
public class FooIterator<E> implements Iterator<E> {
public FooIterator(Collection<Bar> bars, BarConverter<E> converter) {
innerIterator = bars.iterator();
this.converter = converter;
}
#Override
public E next() {
Bar bar = innerIterator.next();
return converter(bar);
}
}
It is not possible to instantiate a type parameter like that.
A workaround is to pass the Class<E> type parameter in the constructor, along with the Collection<Bar>:
private Class<E> clazz;
public FooIterator(Collection<Bar> bars, Class<E> clazz) {
this.clazz = clazz;
innerIterator = bars.iterator();
}
And then in next() method, you can make use of reflection to create instance of E:
#SuppressWarnings("unchecked")
#Override
public E next() {
Bar bar = innerIterator.next();
E instance = null;
try {
instance = clazz.getConstructor(Bar.class).newInstance(bar);
} catch (Exception e) {
e.printStackTrace();
}
if (instance == null) {
// throw an unchecked exception
}
return instance;
}
P.S: You should in general do a better exception handling, than I've used here. I've just catched all the exception in Exception for brevity. In practice, you should have catch block for each specific exception.
Also, rather than using e.printStackTrace(), you can log some helpful message.
While instantiating FooIterator, you need to pass an extra argument - the class for which you are creating the iterator.
This feels a bit hacky, but with an interface and a method which simply constructs itself, you could do this:
interface Barable
{
Barable construct(Barable bar);
}
class Bar implements Barable
{
Bar(Barable bar)
{
//Do stuff
}
#Override
public Barable construct(Barable bar)
{
return new Bar(bar);
}
}
class FooIterator<E extends Barable> implements Iterator<E>
{
public FooIterator(Collection<Bar> bars)
{
innerIterator = bars.iterator();
}
#Override
public boolean hasNext()
{
return innerIterator.hasNext();
}
#SuppressWarnings("unchecked")
#Override
public E next()
{
Bar bar = innerIterator.next();
return (E) bar.construct(bar);
}
#Override
public void remove()
{
throw new UnsupportedOperationException("Don't remove from FooIterator!");
}
private Iterator<Bar> innerIterator;
}
A possible solution could be to parameterize Bar and add a method to it to create a new E. Something like this:
class Bar<E> {
// ... more implementation ...
public E build() {
// create your `E` object here
}
}
and then your code would do something like this:
public class FooIterator<E> implements Iterator<E> {
public FooIterator(Collection<Bar<E>> bars) {
innerIterator = bars.iterator();
}
#Override
public boolean hasNext() {
return innerIterator.hasNext();
}
#SuppressWarnings("unchecked")
#Override
public E next() {
Bar<E> bar = innerIterator.next();
return bar.build();
}
#Override
public void remove() {
throw new UnsupportedOperationException("Don't remove from FooIterator!");
}
private Iterator<Bar<E>> innerIterator;
}
I have a code like the following.
public class DefaultIterator<E> implements Iterator<E> {
private E[] array;
private int i = 0;
public DefaultIterator(E[] array) {
this.array = array;
}
#Override
public boolean hasNext() {
return false;
}
#Override
public E next() {
return array[i++];
}
#Override
public void remove() {
}
}
// here is my execution.
public Iterator<String> createNewIterator(Iterator<String>... generalIterators) {
return new DefaultIterator<Iterator<String>[]>(generalIterators);
}
I am getting the compilation error at the execution code. can somebody explain why it is failing and how to fix it?
Thanks.
So the complaint is that none of the generic types match up between the field declaration, the constructor declaration, and the method declaration.
You want:
public Iterator<String> createNewIterator(String... generalIterators) {
return new DefaultIterator<String>(generalIterators);
}
Your return type is another one than expected! DefaultIterator<Iterator<String>[]> isn't compatible with Iterator<String> Choose DefaultIterator<Iterator<String>[]> as your return type, this should solve it.
I want to create my own implementation of ArrayList in java, that can listen when the list is changing and to do action when this happens.
From what I have read, I understand that I can't extend ArrayList and then add listener.
I want to use MyList in class as a variable with public modifier, so users can change it directly and to be done action when he changes it.
class MyList extends ArrayList<object>.... { ... }
class UseOfMyList {
public MyList places = new MyList<Object>();
places.add("Buenos Aires");
//and to be able to do that
List cities = new ArrayList<Object>();
cities.add("Belmopan");
places = cities;
So how to create and when do add,remove or pass another list to MyList an action to be performed?
You're not going to be able to do this by extending ArrayList, as it has no built-in notification mechanism (and, further, because it is has been declared final and thus cannot be extended). However, you can achieve your desired result by creating your own List implementation and adding your "listener" functionality vis a vis the add() and remove() methods:
class MyList<T>{
private ArrayList<T> list;
public MyList(){
list = new ArrayList<>();
...
}
public void add(T t){
list.add(t)
//do other things you want to do when items are added
}
public T remove(T t){
list.remove(t);
//do other things you want to do when items are removed
}
}
Old question, I know.
I apologize in advance for any bad formatting or missing lines of code. I'm a long-time user, first time contributor.
Anyhow, because of the removal of JavaFX from the JDK11, I was forced to write my own version of the ObservableList. Sure, we can plop JavaFX in with JMods or Maven, but it seems like a bit of an overkill just for the FXCollections.
Long Story made Short...er :)
I started out reading this old question and the answer didn't suit my needs fully, so I've added a custom event/listener class.
Figured I could share since this site has improved my coding 10 fold.
public static void main(String[] args) {
BackedList<String> list = new BackedList();
list.addListener(new BackedListListener<String>(){
#Override
public void setOnChanged(ListChangeEvent<String> event) {
if (event.wasAdded()) {
event.getChangeList().forEach(e->{
// do whatever you need to do
System.out.println("added: " + e);
});
}
if (event.wasRemoved()) {
// do whatever you need to dl
event.getChangeList().forEach(e->{System.out.println(e + " was removed");});
}
}
});
Class: BackedObservableList
public class BackedObservableList<T> implements List<T> {
private final List<T> backed;
public BackedObservableList() {
backed = new ArrayList();
}
public BackedObservableList(List<T> backed) {
this.backed = backed;
}
/*
You will want to override every method. For any method that performs an add/remove
operation, you will have to do some coding / testing. I'll do an add() op, a remove()
op, and an interator in this example. Anything that is not an add/remove op, you can straight up delegate it to the underlying list.
Also remember that list.clear() is a removal operation, where you can simply iterate through the backed list and call the overide remove(T t) method, or just plop the whole backed list into the ListChangeEvent<T> class and delegate to the backed array again.
*/
#Override
public boolean add(T e) {
if (backed.add(e)) {
ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(e), backed.indexOf(e) + 1, true, e);
notifyListeners(event);
return true;
}
return false;
}
}
#Override
public boolean remove(Object o) {
if (backed.remove(o)) {
ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(o),
backed.indexOf(o) + 1, false, o);
notifyListeners(event);
return true;
}
return false;
}
/*
The iterator seemed easy enough, until I remembered the iterator.remove() call.
I still haven't fully tested it (it works, but only as far as I've used it)
*/
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
T currentItem = null;
int currentIndex = 0;
#Override
public boolean hasNext() {
return backed.size() > currentIndex;
}
#Override
public T next() {
return currentItem = backed.get(currentIndex++);
}
#Override
public void remove() {
if (backed.remove(currentItem)) {
currentIndex--;
notifyListeners(new ListChangeEvent<T>(backed, currentIndex, currentIndex + 1, false, currentItem));
}
}
};
}
private void notifyListeners(ListChangeEvent<T> event) {
for (BackedListListener<T> listener : listeners) {
listener.setOnChanged(event);
}
}
private final List<BackedListListener> listeners = new ArrayList();
public void addListener(BackedListListener<T> listener) {
listeners.add(listener);
}
Class: ListChangeEvent
It simply provides a reference to the backed list (which you may want to wrap with Collections.unmodifiableList()
public class ListChangeEvent<T> {
private final List<T> source;
private final List<T> changeList;
private final boolean wasAdded;
private final int to, from;
public ListChangeEvent(List<T> source, int from, int to, boolean wasAdded, T... changeItems) {
this(source, from, to, wasAdded, Arrays.asList(changeItems));
}
public ListChangeEvent(List<T> source, int from, int to, boolean wasAdded, List<T> changeItems) {
this.source = source;
this.changeList = changeItems;
this.wasAdded = wasAdded;
this.to = to;
this.from = from;
}
public int getFrom() {
return from;
}
public int getTo() {
return to;
}
public List<T> getSource() {
return source;
}
public List<T> getChangeList() {
return changeList;
}
public boolean wasAdded() {
return wasAdded;
}
public boolean wasRemoved() {
return !wasAdded;
}
}
Class: BackedListListener
/*
Finally a little functional interface... or, because I was too lazy to change it to one, a simple one-liner abstract class with some generics
*/
public abstract class BackedListListener<T> {
public abstract void setOnChanged(ListChangeEvent<T> event);
}
the resp. ;)
private class MyList extends ArrayList<Objects> {
#Override
public void sort(Comparator c) {
super.sort(c);
resetLancamentos(); // call some metod ;)
}
//...
#Override
public boolean removeAll(Collection c) {
//To change body of generated methods, choose Tools | Templates.
boolean ret = super.removeAll(c);
resetLancamentos(); // some metod like fireObjChanged() will do the job too
return ret;
}
}
How do I throw and UnsupportedOperationException on a method? So if I have an Iterable object and I'm trying to disallow the remove method for that object.
In the method below I'm returning an iterable object whose iterator's remove I need to disable by throwing an UnsupportedErrorException. Can I do this within the body of the method or how so?
public Iterable<String> getInNodes (String destinationNodeName) {
if (!hasNode(destinationNodeName))
return emptySetOfString;
else {
for(String e : nodeMap.get(destinationNodeName).inNodes)
{
emptySetOfString.add(e);
}
return emptySetOfString;
}
}
Try this.
#Override
public void remove() {
throw new UnsupportedOperationException();
}
I may have misunderstood your question.
If you have a normal Iterable, and you want to convert it to an Iterable that generates iterators on which remove can not be called, you can use this monstrosity made possible by anonymous subclassing:
Iterable<String> iterable = // normal Iterable<String> you already have...
Iterable<String> noRemoveIteratorGeneratingIterable = new Iterable<String>() {
#Override
public Iterator<String> iterator() {
return new Iterator<String>() {
Iterator<String> internalIterator = iterable.iterator();
#Override
public boolean hasNext() {
return internalIterator.hasNext();
}
#Override
public String next() {
return internalIterator.next();
}
#Override
public void remove() {
throw new UnsupportedOperationException("Nope!");
}
};
}
};
In your class you can just #Override the original method
public class myIterable extends Iterable {
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
Then create Objects of this class instead of original Iterable.
You can try throwing the message with appropriate message as well:
public void remove() {
throw new UnsupportedOperationException("Remove is unsupported on this object");
}
I am trying to understand Java Iterator and Iterable interfaces
I am writing this class
class MyClass implements Iterable<String> {
public String[] a = null;
public MyClass(String[] arr) {
a = arr;
}
public MyClassIterator iterator() {
return new MyClassIterator(this);
}
public class MyClassIterator implements Iterator<String> {
private MyClass myclass = null;
private int count = 0;
public MyClassIterator(MyClass m) {
myclass = m;
}
public boolean hasNext() {
return count < myclass.a.length;
}
public String next() {
int t = count;
count++;
return myclass.a[t];
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
It seems to be working.
Should I have:
Myclass implements Iterable<Stirng>, Iterator<String> {
}
Or I should put MyClassIterator outside MyClass as
class MyClass implements Iterable<String> {
public String[] a = null;
public MyClass(String[] arr) {
a = arr;
}
public MyClassIterator iterator() {
return new MyClassIterator(this);
}
}
public class MyClassIterator implements Iterator<String> {
private MyClass myclass = null;
private int count = 0;
public MyClassIterator(MyClass m) {
myclass = m;
}
public boolean hasNext() {
return count < myclass.a.length;
}
public String next() {
int t = count;
count++;
return myclass.a[t];
}
public void remove() {
throw new UnsupportedOperationException();
}
}
Which one is better?
You should almost never implement both Iterable and Iterator in the same class. They do different things. An iterator is naturally stateful - as you iterate using it, it has to update its view of the world. An iterable, however, only needs to be able to create new iterators. In particular, you could have several iterators working over the same original iterable at the same time.
Your current approach is pretty much okay - there are aspects of the implementation I'd change, but it's fine in terms of the separation of responsibilities.
You were on track with your first try. MyClass only needs to implement Iterable<String>, which in turn requires you to provide an Iterator<String> implementation to return from Iterable<String>.iterator().
There's no need to put the MyClassIterator outside of MyClass because in most cases you will never even need to directly use the Iterator<String> (it's used implicitly by the for .. in .. syntax on Iterable<String>s), and in all other cases the interface is sufficient unless you actually add additional behavior to the implementation (which you likely won't ever need to do).
Here's how I'd do it, see comments inlined:
import java.util.Iterator;
class MyClass implements Iterable<String>{
public String[] a=null; //make this final if you can
public MyClass(String[] arr){
a=arr; //maybe you should copy this array, for fear of external modification
}
//the interface is sufficient here, the outside world doesn't need to know
//about your concrete implementation.
public Iterator<String> iterator(){
//no point implementing a whole class for something only used once
return new Iterator<String>() {
private int count=0;
//no need to have constructor which takes MyClass, (non-static) inner class has access to instance members
public boolean hasNext(){
//simplify
return count < a.length;
}
public String next(){
return a[count++]; //getting clever
}
public void remove(){
throw new UnsupportedOperationException();
}
};
}
}
You should not do Myclass implements Iterable<String>,Iterator<String>{ since iterators are single-use. With the exception of list iterators, there's no way to return them to the start.
Incidentally, you can skip the
MyClass myClass;
public MyClassInterator(MyClass m){
myclass=m;
}
and instead of referencing
myClass
reference
MyClass.this
Your inner class is not static, so MyClass.this will reference the instance of the enclosing class that created it.