this keyword doesn't represent an object - java

Does anyone know why can we loop through the "this" keyword here (in the subsetOf method)? To my knowledge this represents a JAVA object. Some extensive explanations are welcomed, would like to know why "this" can work in this way.
public class ArrayListSet<E> implements Set<E> {
private ArrayList<E> elements;
public ArrayListSet() {
elements = new ArrayList<>();
}
#Override
public void add(E e) {
if (!elements.contains(e))
elements.add(e);
}
#Override
public void remove(E e) {
elements.remove(e);
}
#Override
public boolean contains(Object e) {
return elements.contains(e);
}
#Override
public int size() {
return elements.size();
}
#Override
public boolean subsetOf(Set<?> other) {
for (E e : this) {
if (!other.contains(e))
return false;
}
return true;
}
}

You are declaring a class which implements the Set interface which itself extends the Iterable through the Collection interface. Any Object which is an implementation of the Iterable interface can be used inside a for-each loop.
So the inheritance hierarchy is this for your class:
Iterable
^
|
Collection
^
|
Set
^
|
ArrayListSet
Also the this keyword always refers to the current instance. In your code when you execute the subsetOf() the this will point to an instance of ArrayListSet (which was used to invoke the subSetOf() method) which is a type of Iterable through inheritance, so you can use it in a for-each loop.
Also since you are implementing a Set you need to supply an implementation of the Iterator<E> iterator(); method defined in the Set interface to make it an Iterable.
As implementations of the Iterable interface requires a iterator() method which returns an instance of the Iterator object. The Iterator Object will be used by the for-each loop to iterate over the elements of the ArrayListSet.
The implementation of the Iterator type returned from the iterator() method actually defines the iteration logic used by the for-each loop.
To use any Object in a for-each loop:
Step 1: Extend Iterable directly or through other Iterable types.
Step 2: Provide implementation of the Iterator iterator() method inherited from the Iterable interface.
Step 3: Implement an Iterator and return its instance from the iterator() method.

You can iterate through this since it represents a set. The set is iterable. Therefore it is valid syntax.

Related

Meaning of "this" in this code?

public boolean contains(Object o) {
for (E x : this)
if (x.equals(o))
return true;
return false;
}
Can someone tell me what excatly means "this" in this code? Can I write it without this and how?
Here this represents object on which current method was invoked. For instance if you have a.contains(x) then inside contains method this will return reference to same object as held in a reference variable.
Since you ware able to use this in for-each it means that contains method is placed in class which implements Iterable<E> interface because for-each can iterate only over:
arrays like String[] array = ...; for(String s : array){...}
instances of classes which implement Iterable<E> like List<String> where we can write for(String s : list){...}
To avoid this you can explicitly add to your method parameter of class which contains this method, like
public boolean contains(YourClass yc, Object o) {
//and use that parameter in loop instead of `this`
for (E x : yc)
if (x.equals(o))
return true;
return false;
}
but this means you would need to call such method in a way a.contains(a,x) so it needs to repeat a twice (not to mention it can allow us to pass other instance of our class than a like a.contains(b,x)).
To avoid this repetition we can make contains method static which will allow to invoke it via YourClass.contains(a,x). But this way we need to resign from one of basic OOP concepts - polymorphism - since it doesn't work with static methods.
Compiler solves it using first solution, so it compiles our methods like they would be written (and we actually CAN write methods that way) as
public boolean contains(YourClass this, Object o) {
// ^^^^^^^^^^^^^^
...
}
Then when we write a.contains(x) it is compiled as if we would invoke a.contains(a,x).
this is a object of the class that contains your contains() method. It refers to the object of that class for which the method is executed.
Putting it after the : of an enhanced for loop means that the class that contains this method must implement Iterable<E>, since the enhanced for loop can be used to iterate over either arrays or instances of classes that implement the Iterable interface. This means your class is able to iterate over some collection of E elements. E is probably a generic type parameter`.
In order to write your method without this, you would have to supply a reference to some alternative object that implements Iterable<E>, but I don't see the point of doing that.
What exactly means this in this code?
It is always a reference to the current instance. I assume your class implements the Iterable<T> interface and overrides the Iterator<T> iterator() method from it.
The loop is just a syntax sugar for the enhanced for statement. According to the specification (§14.14.2.):
for ({VariableModifier} UnannType VariableDeclaratorId : Expression)
Statement
The type of the Expression must be Iterable or an array type (§10.1), or a compile-time error occurs.
If the type of Expression is a subtype of Iterable, then the translation is as follows.
If the type of Expression is a subtype of Iterable<X> for some type argument X, then let I be the type java.util.Iterator<X>; otherwise, let I be the raw type Iterator.
The enhanced for statement is equivalent to a basic for statement of the form:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
{VariableModifier} TargetType Identifier = (TargetType) #i.next();
Statement
}
Usually, a class implements the Iterable to provide to an API user the ability of being allowed to iterate over the internal collection hiding the actual implementation.
Can I write it without this and how?
Use the logic you have written for the inner iterator.
Use the implementation of the underlying collection (if it's and it suits).
Choose one of the options mentioned above and rewrite into a standard for.
Keyword this is just a reference to the current object.
Here is a example how can be this used:
public class Person {
public final String name;
public Person(String name) {
// name = name;
// which one is an argument, and which one is class field?
// by default, both are reference on argument
// using "this" to access class field
this.name = name;
}
public void copyFields(Person other) {
// current object's reference is the same as other object reference
// in other words "this" and "other" are the same instances
// example:
// Person p1 = new Person("a");
// Person p2 = p1; // p2 is now pointing on the same memory address
// // as p1, so both are pointing on the same object
// // stored in memory.
// p1.copyFields(p2);
if (this == other) { // copying from self? useless...
return;
}
this.name = other.name;
}
}
Anything that implements Iterable interface has method which returns Iterator instance, which is implicitly used by foreach loop to iterate over items hold by object. Iterator
has methods hasNext() which returns true, if there is another object
in iterable container, relative to current position, and next() which returns
next object or throws NoSuchElementException if there is no next object (last invokation of hasNext() has returned false).
Here is a simple example of Iterable implementation with contains methods:
public class Customer extends Person implements Iterable<Item> {
private final List<Item> list = new LinkedList<>();
public final String name;
public Customer(String name) {
this.name = name;
}
public void add(Item item) {
list.add(item);
}
// implementing iterable interface
#Override
public Iterator<Item> iterator() {
return list.iterator();
}
// some contains implementations
public boolean contains1() {
for (Item item : this) { // customer implements Iterable = OK
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains2() {
for (Item item : list) { // list implements Iterable = OK
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains3(Object o) {
for (Iterator<Item> iter = iterator(); iter.hasNext(); ) {
Item item = iter.next();
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains4(Object o) {
for (Iterator<Item> iter = list.iterator(); iter.hasNext(); ) {
Item item = iter.next();
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains5(Object o) {
Iterator<Item> iter = iterator();
while (iter.hasNext()) {
Item item = iter.next();
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains6(Object o) {
Iterator<Item> iter = list.iterator();
while (iter.hasNext()) {
Item item = iter.next();
if (o.equals(item)) {
return true;
}
}
return false;
}
public boolean contains7(Object o) {
return list.contains(o);
}
}
Methods are defined in classes, not in objects.
But they are (generally) invoked from objects.
Methods - as they are defined in classes - don't know in advance which object will call them.
So there is a mechanism (implemented by a hidden parameter this) by which the object - when calling a method - secretively passes the address of itself to parameter this.
(In other programming languages may be used other names, as Me or self.)
I would put it in points for you
When we create a new instance of a class then the non static methods and non static member fields are part of it. We access these methods and fields using . operator.
All the non static method or member fields has access to this. The this keyword simply is a reference to the current object upon which that method is executed upon.
Any class which implements Iterable interface can be used with enhanced For-Loop.
Enhanced for loop uses a syntax
for (Object object : objectOfIterableType)
If the class implementing Iterable interface is parametized, suppose its E. then its what you have to in your code.
for (E x : this)
It means current class has the behaviour of being iterable and can be iterated on the collection of items it holds. Above statement will be executed for each item in the collection of items of type E represented by by the current object referred by this keyword. In each iteration x will represent an item from those contained items.

Why isn't a for-each loop accepting an instance of the Iterable class?

Iterable<Position<Integer>> iterable = list.positions();
Iterator<Position<Integer>> iter = iterable.iterator();
while (iter.hasNext()) {
System.out.println(iter.next().getData());
}
The above code works with no issues. list is just an instance of a List class that I wrote. It contains elements of the Integer type.
for (Position<Integer> pos : iterable) {
}
This code fails at the part past the colon. This should be equivalent to the first piece of code, the one with the while loop. So I don't understand why the for-each loop has an error. The error says: "Can only iterate over an array or an instance of java.lang.Iterable" - but iterable already is Iterable, isn't it? What am I missing here?
the following is the full code implementing the aforementioned methods and types.
private class PositionIterator implements Iterator<Position<E>> {
private Position<E> cursor = first();
private Position<E> current = null;
public boolean hasNext() {
return cursor.getData() != null;
}
public Position<E> next() {
if (cursor == null) throw new NoSuchElementException("reached the end of the list");
current = cursor;
cursor = after(cursor);
return current;
}
}
private class PositionIterable implements Iterable<Position<E>> {
public Iterator<Position<E>> iterator() {
return new PositionIterator();
}
}
public Iterable<Position<E>> positions() {
return new PositionIterable();
}
these are nested classes within another class called PositionalList<E>. In the interest of keeping this post compact, I decided to omit the outside class. It's just a bunch of getter and setter methods that are typical for a List class.
public interface Iterable<E> {
public Iterator<E> iterator();
}
^that's the Iterable interface being implemented by PositionIterable
public interface Iterator<E> {
boolean hasNext();
E next();
}
^And that's the Iterator interface.
The enhanced for loop accepts an Iterable, not an Iterator. iter is an Iterator.
Therefore :
for (Position<Integer> pos : iter)
Should be :
for (Position<Integer> pos : iterable)
EDIT : Based on the comments, your problem must be hiding java.lang.Iterable by your custom Iterable interface. If your iterable variable is of the type of your custom Iterable interface, it can't be used by the enhanced for loop, which accepts java.lang.Iterable.
You shouldn't have any issues running that code. Here's my local test code
public static void main(String[] args)
{
Iterable<String> iterable = Arrays.asList("foo",
"bar");
for (String anIterable : iterable)
{
System.out.println(anIterable);
}
}
If you have created a local class or interface called Iterable, that's the only reason I could think why this wouldn't work. If you have done that, delete it and then maybe go back and review the purpose of interfaces too.

Can ListIterator safely be susbtituted for Iterator? (Implementing a CopyOnWrite wrapper for List)

I have many instance in code where a Collection, most usually a List is returned from a method and to account for the caller possibly altering that list, a defensive copy is made.
The JDK does not seem to provide a wrapper for this purpose, so I'm trying to roll my own (Note: java.util.concurrent.CopyOnWriteArrayList is not what I'm looking for here).
Schematically, what I'm trying is:
public class CopyOnWriteList<E> extends List<E> {
protected List<E> list;
protected boolean isCopied;
public CopyOnWriteList(List<E> list) {
this.list = list;
}
private void ensureCopy() {
if (!isCopied) {
list = new ArrayList<E>(list);
isCopied = true;
}
}
public E get(int i) {
return list.get(i);
}
public boolean add(E e) {
ensureCopy();
return list.add(e);
}
// ... many more simple methods
}
For most of the API this is simple enough, but looking at java.util.ArrayList I found, that for the method iterator() it returns a different implementation than for listIterator(), although is ListIterator extends its Iterator and it doesn't add any new members.
I wonder if there is a deeper reason behind this - I planned simply to implement iterator() and listIterator() all returning the same type of iterator - a ListIterator. Is there any logical reason why one should not return a ListIterator from the iterator()-method?
ListIterator extends Iterator. So if you return an object that implements ListIterator then it obviously also implements Iterator. But you also can decide to return different object that only implements Iterator, because the implementation could be more effective. The decision is up to you.

How to generate an Iterator from an array of certain object

private SomeObject[] all_objs;
public Iterator<SomeObject> iterator() {
//
}
What is the best way to get an iterator from an array of SomeObject?
EDIT
So there is no way to generate iterator without using the wrappers like ArrayLists or HashSets ?
You could write your own class that implements Iterator<SomeObject>. Simply implement the methods of the interface. If you don't want the users of the iterator from removing items from the array (since it isn't an ArrayList), then throw an UnsupportedOperationException if this method is called.
Of course if you use an ArrayList<SomeObject> then the iterator() method would only have to return the iterator from the ArrayList making your life much easier.
Using the List iterator:
import java.util.List;
import java.util.Arrays;
public <T> Iterator<T> iterator() {
List<T> list = (List<T>) Arrays.asList(all_objs);
return list.iterator();
}
You can also look at the code of java.util.ArrayList. Here is how you should implement it.
T=SomeObject //Your Class
public YourIterable<T> implements Iterable<T>{
//**Iterable** Implementing this interface allows an object
//to be the target of the "foreach" statement.
public Iterator<T> iterator() {
return new Itr();
}
private class Itr implement Iterator<T> {
//Complex Implementation - You have to maintain a Cursor to keep track of
// which record was accessed
boolean hasNext() {
//Returns true if the iteration has more elements.
}
T next() {
//Returns the next element in the iteration.
}
void remove() {//Remove
}
}
}

Accessor methods for Collections in Java

Given a generic class:
class MyClass (
private List l = new LinkedList <String>();
public void addElement (String s) (l.add (s);)
.............
)
an accessor method that allows me to iterate on the list as it should be?
I had decided to implement a method that returns an iterator directly, but does not seem correct because it could change the list from the outside with remove ().
What do you think?
import java.util.*;
public Iterator<String> elements() {
return Collections.unmodifiableList(elements).iterator();
}
If you don't mind exposing the fact that the elements are stored as a List, you could also use do:
public ListIterator<String> elements() {
return Collections.unmodifiableList(elements).listIterator();
}
If you want to allow callers to use the "foreach" syntax, you might want to return an Iterable:
public Iterable<String> getElements() {
return Collections.unmodifiableList(elements);
}
And, again, if you don't mind exposing that the elements are returned as a List, this last solution could return List<String>
Most common way would be to implement Iterable interface but since you don't want to expose remove method you can follow the advice from NamshubWriter or provide your implementation of get(index) and size() methods (assuming your class should behave like a List). This will allow index based iteration.
however such a thing would be fine?
public Iterator<String> getList(){
return new Iterator<String>(){
Iterator<String> i=l.iterator();
public boolean hasNext() {
return i.hasNext();
}
public String next() {
if(!i.hasNext()) throw new NoSuchElementException();
return i.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
need a method that let me just browse the collection elements and preserve encapsulation, method unmodifiable ... I know but I can not use it.

Categories