3

I have such method:

public void show(Object o)
{
   //show content of object
}

and I would like to pass to it TreeSet or HashMap. But its a different iteration, I mean, when I want to show a content of TreeSet, I use that code:

 while ( iter.hasNext() )
    {
      System.out.println( iter.next());
    }

but when I have a HasMap, I print it like this:

Iterator iterator = map.keySet().iterator();  

while (iterator.hasNext()) {  
   String key = iterator.next().toString();  
   String value = map.get(key).toString();  

   System.out.println(key + " " + value);  
} 

Is there a way to show the content of a collection, when I dont know, if user pass a TreeSet or HashMap? I cant do any conversion in show method (thats not the point). Any ideas?

mazix
  • 2,540
  • 8
  • 39
  • 56
  • 4
    Why don't you just create two methods, eg: `show(TreeSet t)` and `show(HashMap m)`? – NullUserException Nov 21 '12 at 22:10
  • @NullUserException: I know I can do this, but I read on someones blog that its possible - but dont know how to do this:) (There were no code example) and Im just wondering if its REALLY possible:) – mazix Nov 21 '12 at 22:12
  • You can combine the two methods, but to get both the key and value from the map you need to know it is a map, so you end up using instanceof. The two show methods suggested in @NullUserException's comment is simpler and cleaner. – Patricia Shanahan Nov 21 '12 at 22:15
  • `o.toString()` can do the trick, unless you don't like the default formatting. – Code-Apprentice Nov 21 '12 at 22:15
  • By the way, if you want to just find out what the contents of the set or map are, you can just call `System.out.println()` on them. Just saying. – NullUserException Nov 21 '12 at 22:16

4 Answers4

4

Not directly, but if your method is declared as:

public <T> void show(Iterable<T> iterable) {
  for(T t: iterable) {
    System.out.println(t);
  }
}

then you can use it like this:

show(set);
show(map.entrySet());

Not exactly what you want, but Map and Set are inherently different and you can't really treat them the same way (polymorphically).

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
1
if (o instanceof Map) {
            HashMap map = (HashMap) o;
            Iterator iterator = map.keySet().iterator();

            while (iterator.hasNext()) {
                String key = iterator.next().toString();
                String value = map.get(key).toString();

                System.out.println(key + " " + value);
            }
        } else if (o instanceof Set) {
            TreeSet tree = (TreeSet) o;
            Iterator iter = tree.iterator();
            while (iter.hasNext()) {
                System.out.println(iter.next());
            }
        }
mezzie
  • 1,276
  • 8
  • 14
1

The answer is yes, but it's a little ugly:

public static void display(Object o) {
    if (o instanceof Iterable) { // includes Sets, Lists etc
        for (Object element : (Iterable<?>) o) {
            System.out.println(element);
        }
    } else if (o instanceof Map) {
        for (Map.Entry<Object, Object> entry : ((Map<Object,Object>) o).entrySet()) {
            System.out.println(entry.getKey() + " " + entry.getValue());
        }
    } else if (o != null && o.getClass().isArray()){
        // How to detect and handle arrays
        for (Object element : (Object[])o) {
            System.out.println(o);
        }
    } else {
        // default case
        System.out.println(o);
    }
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722
0

Following more closely object-oriented approach, you can create decorators for classes TreeSet and HashMap. Then, instead of calling show(object), you would be calling object.show(), which is more clean IMHO and follows the OOP principles, such as Encapsulation and Abstraction:

public interface Showable {
    void show();
}

public class ShowableTreeSet<E> extends TreeSet<E> implements Showable
{
    private TreeSet<E> delegate;

    public ShowableTreeSet(TreeSet<E> delegate) {
        this.delegate = delegate;
    }

    public void show() {
        for (E e : delegate) {
            System.out.println(e);
        }
    }

    public boolean add(E e) {
        return delegate.add(e);
    }

//all other delegate methods
}

public class ShowableHashMap<K, V> extends HashMap<K, V> implements Showable 
{
    private HashMap<K, V> delegate;

    public ShowableHashMap(HashMap<K, V> delegate) {
        this.delegate = delegate;
    }

    public void show(){
        Iterator<K> iterator = delegate.keySet().iterator();  

        while (iterator.hasNext()) {  
           String key = iterator.next().toString();  
           String value = delegate.get(key).toString();  

           System.out.println(key + " " + value);  
        } 
    }

    public int size() {
        return delegate.size();
    }

//all other delegate methods
}

So then you would just have to wrap you showables around any actual object you would use:

ShowableTreeSet<String> sts = new ShowableTreeSet<String>(new TreeSet<String>());
sts.show();

or if you wanted just any Showable for printout, you could go:

Showable showable = new ShowableTreeSet<String>(new TreeSet<String>());
showable.show();

You could create these decorators to just about anything - Iterable, List, Collection, etc... and then use dependency injection to use whatever implementation of Collection (Iterable, List...) you happen to use.

Jakub Zaverka
  • 8,816
  • 3
  • 32
  • 48