I have a class Example witch private field Hashmap<Integer, CustomObject>. My goal is to access all instances of CustomObject in this class using the Iterable interface. First, I declare Example to implement Iterable<CustomObject>. Then I call iterator() method. However, I don't know if I should specify hasNext() etc, what to put in main code? Here is what I have so far:
public class Example implements Iterable<Songs>{
private HashMap <Integer, CustomObject>;
#Override
public Iterator<CustomObject> iterator() {
for (CustomObject customObject: this){
System.out.println(customObject);
}
public static void main(String[] args) {
Example.iterator();
}
Actually HashMap has a method Map::values() that returns a collection of the values as a Collection<T> which actually is-an Iterable<T> (hence can return an Iterator<T>).
Map<Integer, CustomObject> map = new HashMap<>();
Iterator<CustomObject> iterator = map.values().iterator();
Moreover, your code has several errors:
private HashMap <Integer, CustomObject>; misses the field name and possibly an initiation.
Implementing Iterable<Songs> you have to override public Iterator<CustomObject> iterator(). I assume you mean class Example implements Iterable<CustomObject>.
Iterable::iterator is not a static method, so you cannot call Example.iterator();.
A complete example assuming the Example is an iterable delegate of the HashMap map like in your class (you have forgotten to name it, otherwise it would not compile, and initialize it), then you can do this:
public class Example implements Iterable<CustomObject> {
private Map<Integer, CustomObject> delegate = ...; // initialize + data
#Override
public Iterator<CustomObject> iterator() {
return this.delegate.values().iterator();
}
}
And use like at any of these snippets:
As long as Example is-an Iterable, then it can be used with enhanced loops:
for (CustomObject customObject: new Example()) { // Iterable with enhanced loop
System.out.println(customObject);
}
Through an actual Iterator:
Iterator<CustomObject> iterator = new Example().iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
Through Stream as long every Iterable returns its Spliterator:
StreamSupport.stream(new Example().spliterator(), false)
.forEach(System.out::println);
Related
I'd like to map the Label -> Value of a generic enum instance. This is feasible with this code:
public static <T extends Enum<T>> List<Map<String, String>> mapEnumValues(T[] myEnumValues) {
List<Map<String, String>> list = new ArrayList<>();
for (T myEnumValue : myEnumValues) {
Map<String, String> map = new HashMap<>();
map.put("label", myEnumValue.name());
map.put("value", myEnumValue.toString());
list.add(map);
}
return list;
}
But now I want to use another key for the map, which is for instance a method getLabel() implemented by every one of my enums. For example, given:
public interface Labelizable{
public String getLabel();
}
static public enum Options implements Labelizable {
option01("Option 01", 1), option02("Option 02", 2)
... constructor, getLabel(), ....
So I'd like to replace that row of code with:
map.put("label", myEnumValue.getLabel()); // instead of .name()
In order to do that I should declare something on the signature thst forces the parameter to be an enum that implements the getLabel() method. I tried, for example,
public static <T extends Enum<T implements Labelizable>>
and some other syntax like this with no success. Is there any way to achieve this behaviour, or the fact that enums can't inherit prevent such a method?
The syntax is:
public static <T extends Enum<T> & Labelizable>
List<Map<String, String>> mapEnumValues(T[] myEnumValues) {
You put the superclass that your generic parameter has to inherit first, then the interfaces that it has to implement, all separated by &.
I am doing this assignment where we have to create 2 types of object,
public class Person implements Cloneable, Comparable<Person>
and
public class Book implements Cloneable, Comparable<Book>
The main task of this program is to sort the two types using its own compare functions as following:
compareTo(Person o)
compareTo(Book o)
So, I created 2 ListArray as following in the main function to store the book and person objects as following:
List<Book> bookArray = new ArrayList<Book>();
List<Person> peopleArray = new ArrayList<Person>();
And I have my sorting algorithm implemented in another class like the following:
public class Sort{
Comparable<Object>[] values;
public Sort(List<Object> inputArray) {
this.values = (Comparable<Object>[]) inputArray.toArray();
}
public doSort() {
//sort implementation...
}
The problem is when calling this function using the arrays above
Sort sorter = new Sort(peopleArray);
sorter.doSort();
Eclipse shows the error saying "The constructor Sort(List) is undefined."
What am I doing wrong here?
Thank you in advance.
You can pass any class instance to Object type. but List is not a parent of List. Those are just two different types.
You can say
public Sort(List<? extends Object> inputArray)
so that it will accept any type.
Just because you named the field "personArray" does not make it an array - you are passing in a List when the constructor is declared to expect an array.
I recommend that you never use arrays unless you absolutely have to; use Collections instead, because they are so much easier to deal with and, contrary to popular belief, the performance difference is negligible.
If you remove all arrays from your code, and add some generics, it will all work:
public class Sort<T extends Comparable<T>> {
private List<T> values;
public Sort(List<T> values) {
this.values = values;
}
public void doSort() {
Collections.sort(values);
}
}
Note that this whole class adds very little value, if sorting is all it does. Your client code can just code this one line instead:
Collections.sort(values);
Its not so clear but If am right Whenevr you use another new class for sorting that is probably implements COMPARATOR.
so in ur example Sort class should be
Class Sort implemets Comaparator<Person> {
public void Compare(Object 01,Object 02) {
return (Person)o1.comapareTo(Person)o2;
}
then in main, call
Collections.sort(list,new Sort());
lly u need to do for book too.
I have the follow code
public class SBag<Item> implements BagInterface<Item>, Iterable<Item> {
And when I try to compile I get
SBag.java:12: error: SBag is not abstract and does not override abstract method
iterator() in Iterable
public class SBag<Item> implements BagInterface<Item>, Iterable<Item>{
^
where Item is a type-variable:
Item extends Object declared in class SBag
My task is to implement Iterable without using an inner-iterator class, but I am unsure of how to do this because I get that error when compiling. I have the followin methods add(), isFull(), toArray(), isEmpty(), getCurrentSize(), remove(), clear(), and toString(). The overall goal is to be able to use a for-each loop, but I am unsure of how to proceed from here.
An Iterator as an inner class would look like this:
class MyIterable implements Iterable {
public Iterator iterator() {
return new Iterator() {
public boolean hasNext() {...}
public Object next() {...}
void remove();
}
}
}
In contrast, an Iterator that's not an inner class might look more like:
class MyIterable implements Iterable {
public Iterator iterator() {
return new MyIterator();
}
}
class MyIterator {
public boolean hasNext() {...}
public Object next() {...}
void remove();
}
This is another way that's technically speaking not an inner class, but some people will look at you funny if you say that:
class MyIterable implements Iterable {
public Iterator iterator() {
return new MyIterator();
}
static class MyIterator {
public boolean hasNext() {...}
public Object next() {...}
void remove();
}
}
When you implement Iterable, you can then use for:each loop syntax:
Implementing this interface allows an object to be the target of the
"foreach" statement.
Iterable is a generic interface, you should implement the method it contains:
public class MyIterable<E> implements Iterable<E>{
public Iterator<E> iterator() { // <--- Implement me!
return new CustomIterator<E>();
}
}
And then, for example, you can do something like this:
public class CustomIterator<T> implements Iterator<T> {
public boolean hasNext() {
//...
}
public T next() {
//...
}
public void remove() {
//...
}
}
While [this answer] provides the regular syntax for Iterable implementations, an Iterator can be useful without an Iterable-implementing class. For example:
public class DoesntIterate{
public void coolMethod(){
//Do stuff
Iterator iter = getMyIterator();
while(iter.hasNext()){
//Do stuff with iter.next()
}
}
private Iterator getMyIterator(){
return new MyIterator();
}
private class MyIterator implements Iterator{
...
}
}
With this sort of paradigm, it's conceivable that you might use different iterators for different purposes all within the same class.
From an OOP perspective, you should never be making a class implement Iterable when it doesn't make sense for that to be an class on which you would iterate (i.e. if the class is not a data/storage structure).
In a class, I have a container:
public class MyClass implements MyClassInterface {
private LinkedList<OtherClass> list; //Need to use 'OtherClass' instead of 'OtherClassInterface here
#Override
public Iterator iterator() {
return list.iterator; //Problem!
}
}
The interface:
public interface MyClassInterface {
//Is
public Iterator iterator();
//Should be
public Iterator<OtherClassInterface>();
}
Then again, OtherClass also has an interface OtherClassInterface.
I want only the interfaces to be used by whom who works with the code.
The problem is that I want to use the full OtherClass inside MyClass but pass an iterator over LinkedList<OtherClassInterface> to the caller of MyClassInterface.iterator().
I could not cast the existing LinkedList<OtherClass> to LinkedList<OtherClassInterface> inside MyClass to return the desired iterator.
How to handle such a situation?
EDIT
Reason why I want this behaviour
For another developer, I want to provide two interfaces: The first gives him access to a higher data structure which contains a lower data structure which he should access by the second interface. In the implementing class of the higher interface I use the type of the lower data structure directly, not over the lower interface.
As mentioned, the other developer wants to use both interfaces. Over the higher one I want to provide an iterator that gives access to elements of the lower interface - but not to the class that implements the interface.
Additional needs
I also want the returned iterator to be "Iterable" i.e. so that I can use the "for each" construct. Is this also possible with *waxwing*s solution? If possible, I wouldn´t like to implement an own iterator - for me this seems not neccessary because I just want to give an iterator over elements of the interface instead of the implementing class.
You could write your own Iterator implementation that converts between the interface and the concrete implementation when returning from next()
The problem with converting List<OtherClass> to List<OtherClassInterface> is that there is no way to prevent the user of the conversion result to put something other than OtherClass objects into the list (of course those elements must implement the OtherClassInterface as well)
Can you define the interface like this?
public interface MyClassInterface {
public Iterator<? extends OtherClassInterface>();
}
list.iterator() should be a valid return value for that method, even when list is List<OtherClass>.
Can you change the interface?
public interface MyClassInterface<T> {
public Iterator<T> iterator();
}
You can always implement your own iterator :
public class MyClass implements MyClassInterface<T> {
private LinkedList<T> list;
#Override
public Iterator iterator() {
return new Iterator<T>() {
int index;
public boolean hasNext() {
return index < list.size();
}
public T next() {
return list.get(index++);
}
public void remove() {
}
};
}
}
didn't test the code
The interface can be defined like this:
public interface MyClassInterface {
public LinkedList<? extends OtherClassInterface> list();
}
Then the implementation should look like this:
#Override
public LinkedList<OtherClass> list() {
return list; //this is the container of type LinkedList<OtherClass>
}
This has the following advantages:
When calling list() by an OtherClass object you will get a LinkedList<OtherClass>
When calling list() by an OtherClassInterface object you will get a LinkedList<OtherClassInterface>
The return value of each can be used in the for-each loop
The iterator can be obtained by list().iterator()
Hey guys, I am fairly new to Java, and I have a question about collections and iterators.
In my code I have a collection (which somewhere down the road extends extends Iterable) and every object is basically a LinkedList.
I need an iterator for that collection, so I've wrote it down this way:
public class A{
LinkedList<B> BList= new LinkedList<B>();
...
public Iterator<B> iterator() {
return BList.iterator();
}
}
Now, the question is, how can I change any method of that iterator?
Or to be more specific, how can I disable the remove method of the iterator?
Thanks.
You could return an iterator of an unmodifiable list:
import java.util.Collections;
...
public class A{
LinkedList<B> BList= new LinkedList<B>();
...
public Iterator<B> iterator() {
return Collections.unmodifiableList(BList).iterator();
}
}
This will wrap your List with an implementation that disallows any changes to the list structure (like removal). You then return an iterator based on the wrapped list.
If you want an unmodifiable list, use the other answer posted here. But if you want to disable only the remove, a possible way is to create a new class that extends the Iterator interface but whose remove() method throws an exception (or simply does nothing) and forwards every other method to the original iterator object:
public class MyIterator implements Iterator {
private Iterator wrappedIterator;
public MyIterator( Iterator it ) {
wrappedIterator = it;
}
public void remove( blabla ) {
//do nothing or raise an error, whatever floats your boat
}
public void otherIteratorMethod() {
wrappedIterator.otherIteratorMethod();
}
}