java generics - how to implement a class that takes a HashSet<T>? - java

Normally when you implement a generic, you have some type T that you want to generalize. I want to write a class that generalizes a HashSet<T>.
I'm trying to write this the following way, but it's not the correct syntax or maybe it's not supported:
public class PermutationHelper<T> implements Iterable<T> {
private HashSet<T> m_set;
private long numberOfPermutations;
private boolean includeEmptyPermutationAsOutput = false;
public PermutationHelper(HashSet<T> set) {
m_set = set;
numberOfPermutations = 2 ^ set.size();
}
public void setIncludeEmptyPermutationAsOutput(boolean value) {
includeEmptyPermutationAsOutput = value;
}
#Override
public Iterator<T> iterator() {
Iterator<T> it = new Iterator<T>() {
long currentIndex = (includeEmptyPermutationAsOutput ? 0 : 1);
#Override
public boolean hasNext() {
return currentIndex < numberOfPermutations;
}
#Override
public T next() {
HashSet<T> result = new HashSet<T>();
return result; // expects T, but is a HashSet<T>..
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
return it;
}
}
I want the Iterator to give me all subsets of the passed-in HashSet<T>.

You can easly do
public class PermutationHelper<T extends HashSet<T>> implements Iterable<T>
in order to 'force' the generic type to be an HashSet or a subtype of a HashSet

What you want is simply
public class PermutationHelper<T> implements Iterable<HashSet<T>>
Your class is generic. You choose to name its generic type T. And it implements Iterable<HashSet<T>>, which means it must have a method
public Iterator<HashSet<T>> iterator()

Related

Strange bug with Streams

So I have created my own Set, which is just a regular set, but has additional functions (for example my set only stores absolute values).
Here is my Code:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet<E> extends HashSet<E> {
private Set<Integer> mySet;
public SortedByAbsoluteValueIntegerSet() {
mySet = new HashSet<Integer>();
}
#Override
public int size() {
return mySet.size();
}
#Override
public boolean add(E e){
return mySet.add(Math.abs((Integer) e));
}
#Override
public boolean remove(Object o) {
return mySet.remove(o);
}
#Override
public boolean contains(Object o){
return mySet.contains(o);
}
#Override
public boolean addAll(Collection<? extends E> c) {
List<Integer> myList = new ArrayList<>();
for (Object e: c) {
myList.add(Math.abs((Integer) e));
}
return mySet.addAll(myList);
}
#Override
public String toString(){
return mySet.toString();
}
}
I had a test case in JUnit, which failed. Because there was some issue with my code. For demonstration purpose, and for me to explain my issue better I have created two functions, which show the problem well.
Here is the problem:
public static void testSortedByAbsoluteValueIntegerSet() {
Set<Integer> set1 = new SortedByAbsoluteValueIntegerSet();
Set<Integer> set2 = new HashSet<>();
set1.add(5);
set1.add(3);
set2.add(5);
set2.add(3);
String x = toString(set1); //x is ""
String t = toString(set2); //t is "3 5"
}
public static String toString(final Collection<Integer> collection) {
return String.join(" ", collection.stream()
.map(i -> Integer.toString(i))
.toArray(String[]::new));
}
So the problem arises in this line:
String x = toString(set1); //x is always an empty string
String t = toString(set2); //t works correctly
When I go through debugger I see that String x is always an empty String and String t works correctly. By the way set1 is representation of my created set and set2 is just a regular hashset.
The question is: how can I fix my SortedByAbsoluteValueIntegerSet class so that the toString() method worked fine with my own created set as well.
P.S I am new to streams and I don't really understand the problem, why does it happens.
It's because you're extending HashSet but also using an internal Set.
When adding, you're adding to the internal Set but when using collection.stream() it calls the inherited HashSet (which is empty).
Easiest for you I beleive would be to remove the internal 'mySet' and call the inherited methods in your overridden methods.
For instance, your add method would be
#Override
public boolean add(E e){
return super.add(Math.abs((Integer) e));
}
(and then you don't need to override size, remove, contains of toString or spliterator)
Full example:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet extends HashSet<Integer> {
#Override
public boolean add(Integer e){
return super.add(Math.abs(e));
}
#Override
public boolean addAll(Collection<? extends Integer> c) {
List<Integer> myList = new ArrayList<>();
for (Integer e: c) {
myList.add(Math.abs(e));
}
return super.addAll(myList);
}
}
I think Tomas F gave better answer
Main problem in your set is using HashSet mySet as field and extending HashSet. In java better to use (field) composition instead of extending to add some functionality to your class. Here you tried use both - it's not a good idea.
Best decision is to use just composition and extending more general class, for example AbstractSet<Integer> and Set<Integer>:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet extends AbstractSet<Integer>
implements Set<Integer>, java.io.Serializable {
private final Set<Integer> mySet;
public SortedByAbsoluteValueIntegerSet() {
mySet = new HashSet<>();
}
#Override
public Iterator<Integer> iterator() {
return mySet.iterator();
}
#Override
public int size() {
return mySet.size();
}
#Override
public boolean add(Integer e) {
return mySet.add(Math.abs(e));
}
#Override
public boolean remove(Object o) {
return mySet.remove(o);
}
#Override
public boolean contains(Object o) {
return mySet.contains(o);
}
#Override
public boolean addAll(Collection<? extends Integer> c) {
List<Integer> myList = new ArrayList<>();
for (Integer e : c) {
myList.add(Math.abs(e));
}
return mySet.addAll(myList);
}
#Override
public String toString() {
return mySet.toString();
}
}
in this case you don't have to implement spliterator, because Set has default implementation using this keyword (which is refer to your set as a Collection)
but also you can implement spliterator in your class (but using such extends and internal Set fields are the bad practice. Also, it's better to get rid of type parameter E and casting elements to Integer:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet extends HashSet<Integer> {
private Set<Integer> mySet;
public SortedByAbsoluteValueIntegerSet() {
mySet = new HashSet<>();
}
#Override
public int size() {
return mySet.size();
}
#Override
public boolean add(Integer e){
return mySet.add(Math.abs(e));
}
#Override
public boolean remove(Object o) {
return mySet.remove(o);
}
#Override
public boolean contains(Object o){
return mySet.contains(o);
}
#Override
public boolean addAll(Collection<? extends Integer> c) {
List<Integer> myList = new ArrayList<>();
for (Integer e: c) {
myList.add(Math.abs(e));
}
return mySet.addAll(myList);
}
#Override
public String toString(){
return mySet.toString();
}
#Override
public Spliterator<Integer> spliterator() {
return mySet.spliterator();
}
}

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>.

How to bypass Java not being able to extend from multiple classes

I think I have a design problem in my Java app, but I cannot figure out how to solve or bypass it.
Say I have an interface and an abstract class implementing it as follows:
public interface IntegerCollection extends Collection<Integer> {
public int sum();
}
public abstract class AbstractIntegerCollection
extends AbstractCollection<Integer> implements IntegerCollection {
public int sum() {
// fancy code to calculate the sum of all collection members (just an example)
}
}
Now I would want to make this class instantiable by using the existing implementations of Collection (e.g., LinkedList); something like this:
public class IntegerLinkedList extends AbstractIntegerCollection, LinkedList<Integer> {
}
IntegerCollection ic = new IntegerLinkedList();
However, this does not work because Java does not support extending several classes. Also it looks quite ugly to me, as there is a mixture of hierarchies.
Of course, I could let IntegerLinkedList implement IntegerCollection instead of letting it extend AbstractIntegerCollection. But then, I would have to repeat the code for sum() in all other implementations (e.g., IntegerArrayList).
Is there a better way to do this?
I'm not sure what exactly, you are trying to achieve, but rather you could implements List instead of extending LinkedList
public class IntegerLinkedList
extends AbstractIntegerCollection
implements List<Integer>
{
}
But, you need to implements all abstract method of List.
Since java 8 it has been possible to include implementations in an interface by using the default keyword. Therefore you don't need AbstractIntegerCollection - all the common code can be put in the interface. Here is an example:
import java.util.Collection;
import java.util.LinkedList;
public class Main {
interface IntegerCollection extends Collection<Integer> {
default int sum() {
int sum = 0;
for (int a : this)
sum += a;
return sum;
}
}
static class IntegerLinkedList extends LinkedList<Integer> implements IntegerCollection {
}
public static void main(String[] args) {
IntegerCollection list = new IntegerLinkedList();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list.sum()); // Prints 6
}
}
This works, but I'm not sure it's a good idea. I'd think very carefully before extending a class like LinkedList. Some people also consider it an anti-pattern to extend generic classes with non-generic ones.
Another thing to be aware of is that it is not possible to write default methods for the methods of Object like equals and toString etc.
Since you are using Java 7, the above solution is not available. However, with a load of tedious forwarding methods, you can do it using composition rather than inheritance. Josh Bloch's book Effective Java gives a very good explanation of why composition is preferable anyway. Here is an (incomplete) example - you'll need to add a few more forwarding methods to avoid UnsupportedOperationExceptions when you try doing other things with the list.
import java.util.*;
public class Main {
abstract static class AbstractIntegerCollection extends AbstractCollection<Integer> {
public int sum() {
int sum = 0;
for (int a : this)
sum += a;
return sum;
}
}
static class IntegerLinkedList extends AbstractIntegerCollection implements List<Integer> {
private final List<Integer> list = new LinkedList<>();
#Override
public Iterator<Integer> iterator() {
return list.iterator();
}
#Override
public int size() {
return list.size();
}
#Override
public boolean addAll(int index, Collection<? extends Integer> c) {
return list.addAll(index, c);
}
#Override
public Integer get(int index) {
return list.get(index);
}
#Override
public Integer set(int index, Integer element) {
return list.set(index, element);
}
#Override
public boolean add(Integer element) {
return list.add(element);
}
#Override
public void add(int index, Integer element) {
list.add(index, element);
}
#Override
public Integer remove(int index) {
return list.remove(index);
}
#Override
public int indexOf(Object o) {
return list.indexOf(o);
}
#Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
#Override
public ListIterator<Integer> listIterator() {
return list.listIterator();
}
#Override
public ListIterator<Integer> listIterator(int index) {
return list.listIterator(index);
}
#Override
public List<Integer> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
// More of these
}
public static void main(String[] args) {
IntegerLinkedList list = new IntegerLinkedList();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list.sum()); // Prints 6
}
}
This solution is far from perfect. For one thing, it would be better if IntegerLinkedList extended AbstractList<Integer> rather than just AbstractCollection<Integer>, but then you couldn't extend AbstractIntegerCollection too.

How is having a wrapper class equals composition as described Joshua Bloch?

I am reading the book effective java by Joshua Bloch. on the item 16 of "favor composition over inheritance", he gives an example of using HashSet and querying how many elements have been added since it was created(not to be confused with current size, which goes down when an element is removed). he provided the following code and here the getAddCount return 6, which I can understand. This should return 3 actually. (this is because HashSet's addAll method is implemented on top of its add method)
import java.util.HashSet;
public class InstrumentedHashSet<E> extends HashSet<E> {
// The number of attempted element insertions
private int addCount = 0;
public InstrumentedHashSet() {
}
public InstrumentedHashSet(int initCap, float loadFactor) {
super(initCap, loadFactor);
}
#Override
public boolean add(E e) {
addCount++;
return super.add(e);
}
#Override
public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return super.addAll(c);
}
public int getAddCount() {
return addCount;
}
public static void main(String[] args) {
InstrumentedHashSet<String> s = new InstrumentedHashSet<String>();
s.addAll(Arrays.asList("Snap", "Crackle", "Pop"));
System.out.println(s.getAddCount());
}
}
Now he explains a way to fix this, using wrapper classes (composition and forwarding). here is where I am having hard time to understand. he provides the following two classes
public class ForwardingSet<E> implements Set<E> {
private final Set<E> s;
public ForwardingSet(Set<E> s) {
this.s = s;
}
public void clear() {
s.clear();
}
public boolean contains(Object o) {
return s.contains(o);
}
public boolean isEmpty() {
return s.isEmpty();
}
public int size() {
return s.size();
}
public Iterator<E> iterator() {
return s.iterator();
}
public boolean add(E e) {
return s.add(e);
}
public boolean remove(Object o) {
return s.remove(o);
}
public boolean containsAll(Collection<?> c) {
return s.containsAll(c);
}
public boolean addAll(Collection<? extends E> c) {
return s.addAll(c);
}
public boolean removeAll(Collection<?> c) {
return s.removeAll(c);
}
public boolean retainAll(Collection<?> c) {
return s.retainAll(c);
}
public Object[] toArray() {
return s.toArray();
}
public <T> T[] toArray(T[] a) {
return s.toArray(a);
}
#Override
public boolean equals(Object o) {
return s.equals(o);
}
#Override
public int hashCode() {
return s.hashCode();
}
#Override
public String toString() {
return s.toString();
}
}
AND
import java.util.*;
public class InstrumentedSet<E> extends ForwardingSet<E> {
private int addCount = 0;
public InstrumentedSet(Set<E> s) {
super(s);
}
#Override
public boolean add(E e) {
addCount++;
return super.add(e);
}
#Override
public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return super.addAll(c);
}
public int getAddCount() {
return addCount;
}
public static void main(String[] args) {
InstrumentedSet<String> s = new InstrumentedSet<String>(
new HashSet<String>());
s.addAll(Arrays.asList("Snap", "Crackle", "Pop"));
System.out.println(s.getAddCount());
}
}
how this works? In the main method, I create an instance of HashSet and using addAll method, I add all the elements of list. but the HashSet invokes its addAll method (which in turn uses its add method), which should be the same as in the first in correct example and I should get value of 6, however this gives me 3.
In
public class InstrumentedHashSet<E> extends HashSet<E> {
you're adding directly to the HashSet because the addAll() is delegating to the super implementation
InstrumentedHashSet<String> s = new InstrumentedHashSet<String>();
s.addAll(Arrays.asList("Snap", "Crackle", "Pop"));
System.out.println(s.getAddCount());
The addAll() internally calls add() which defers to your #Override implementation of add() because of polymorphism
#Override
public boolean add(E e) {
addCount++;
return super.add(e);
}
that increments the count and prints 6 (3 + 1 + 1 + 1).
In
public class InstrumentedSet<E> extends ForwardingSet<E> {
you are adding to
private final Set<E> s;
because the addAll() is delegating to it, so
public static void main(String[] args) {
InstrumentedSet<String> s = new InstrumentedSet<String>(
new HashSet<String>());
s.addAll(Arrays.asList("Snap", "Crackle", "Pop"));
System.out.println(s.getAddCount());
}
and prints 3. Here the add() is being called on the Set<E> s, not on your instance.
The conclusion is that if you are inheriting, you need to understand the side-effects. Do the super method calls invoke any other method calls internally? If so, you need to act appropriately.
Inheritance (start from bottom)
s.add() // s is your InstrumentedHashSet instance, because of polymorphism (inheritance), this adds to the count
this.add() // this is the internal call inside the HashSet#addAll()
super.addAll(...) // this calls the HashSet implementation of addAll which calls add() internally
s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); // s is your InstrumentedHashSet instance
Composition
this.add() // this is the internal call to add() inside the Set implementation
s.addAll() // s is the Set<E> instance
super.addAll(...) // this calls the ForwardingSet implementation of addAll()
s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); // s is your InstrumentedSet instance
InstrumentedSet#getAddCount() returns 6 because the size of the array (3) is added twice!
//InstrumentedSet
public boolean addAll(Collection<? extends E> c) {
addCount += c.size(); //here
return super.addAll(c); //and here!
}
super.addAll(c); calls the add() Method.
More detailed:
InstrumentedSet#addAll -> ForwardingSet#addAll (because of super.addAll) -> HashSet#addAll() (because this is what you give it in the main) -> InstrumentedSet#add (because of polymorphism)
If you want a fix: remove addCount += c.size();
InstrumentedSet#addAll returns 3 because it calls this:
InstrumentedSet#addAll() (adds 3) -> ForwardingSet#addAll (because of super) -> HashSet#addAll (because forwardingset has a field of type HashSet) -> HashSet#add

Defining types on object creation like HashMap<type here>

Very simple question, Im implementing a array enumeration class but cannot remember how to get the correct type back on the nextElement() method. The code is as follows...
public class ArrayEnumeration<Object> implements Enumeration<Object> {
private Object[] data;
private int n = 0;
public ArrayEnumeration(Object[] data) {
this.data = data;
}
#Override
public boolean hasMoreElements() {
return n < data.length;
}
#Override
public Object nextElement() {
n++;
return data[n - 1];
}
}
so object returned from the nextElement method should be the type that was defined when the class was created. I just cannot remember how to do it. So annoying!!!
Many thanks in advance.
Check out the source code of java.util.List for an example:
public interface List<E> extends Collection<E> {
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/List.java
Your methods then use the generic type:
public boolean add(E e);
public E get(int index);
All from the source of the java.util.List..
So in your case:
public class ArrayEnumeration<E> implements Enumeration<E> {
...
#Override
public E nextElement() {
n++;
return data[n - 1];
}
}
Use a type parameter:
public class ArrayEnumeration<T>
implements Enumeration<T>
{
private T[] data;
public ArrayEnumeration(T[] data)
{
this.data = data;
}
// ...
public T nextElement() {}
}
Also, you should consider using Iterator instead. But in any event, arrays implement Iterable, so why are you doing this?

Categories

Resources