2

Below is part of code where map is initialized as:
Map<Integer,Integer> map = new HashMap<>();
and the line which I want to modify the output is

System.out.println("Price and items "+map.toString());
where the output presently is
{100=10,200=5}

I want to display
{100:10,200:5}

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
Chaipau
  • 199
  • 1
  • 5
  • 14

3 Answers3

10

Don't rely on the method toString() as it is an implementation detail that could change from one version of Java to another, you should rather implement your own method.

Assuming that you use Java 8, it could be:

public static <K, V> String mapToString(Map<K, V> map) {
    return map.entrySet()
        .stream()
        .map(entry -> entry.getKey() + ":" + entry.getValue())
        .collect(Collectors.joining(", ", "{", "}"));
}

If you want to have the exact same implementation as AbstractMap#toString() that checks if the key or the value is the current map, the code would then be:

public static <K, V> String mapToString(Map<K, V> map) {
    return map.entrySet()
        .stream()
        .map(
            entry -> (entry.getKey() == map ? "(this Map)" : entry.getKey())
                    + ":"
                    + (entry.getValue() == map ? "(this Map)" : entry.getValue()))
        .collect(Collectors.joining(", ", "{", "}"));
}
Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
  • Watch out - this doesn't work quite the same as `HashMap.toString()` (admittedly in some pretty marginal cases). Check out the source of `AbstractMap.toString()` to see what I mean. – Andy Turner Oct 06 '16 at 12:40
  • Do you mean `key == this ? "(this Map)" : key` or `value == this ? "(this Map)" : value`? If so it is only to avoid infinite loop as it would call `map.toString()` again which is not applicable in this case as it uses a dedicated method – Nicolas Filotto Oct 06 '16 at 12:53
  • I do - but what I mean is that OP asks only to change `=` to `:`, so you should preserve the existing behaviour with respect to self-keyed (or self-valued) entries. – Andy Turner Oct 06 '16 at 12:54
2

Since map is integer integer you can play with the toString() method and replace the undesired chars...

do string replace :)

map.toString().replace("=",":");
ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
  • 1
    Doesn't work if you've got `=` in your keys or values. – Andy Turner Oct 06 '16 at 12:31
  • Prefer `.replace('=', ':')`, since it avoids String literals and doesn't user Regex. – Tom Oct 06 '16 at 12:37
  • @Tom `replace` *never* uses regex. – Andy Turner Oct 06 '16 at 12:38
  • @AndyTurner You might want to check the implementation of it ;). It internally uses `Pattern` with the provided String as a pattern literal. So it still compiles that "regex" (even though it isn't handled as a regex). – Tom Oct 06 '16 at 13:05
  • @Tom interesting. I'd not spotted that. – Andy Turner Oct 06 '16 at 13:06
  • @AndyTurner `replace(char, char)` on the other hand works on that internal char array, which should be faster. But we're talking about milli and nano seconds, I know :D. – Tom Oct 06 '16 at 13:08
2

You can't override the symbols in the toString() method directly.

Whilst you can use String.replace for maps where the keys and values can't contain = (like Integers), you'd have to provide a different implementation in general.

You can see this isn't too tricky to do if you look at the source of AbstractMap.toString():

public String toString() {
    Iterator<Entry<K,V>> i = entrySet().iterator();
    if (! i.hasNext())
        return "{}";

    StringBuilder sb = new StringBuilder();
    sb.append('{');
    for (;;) {
        Entry<K,V> e = i.next();
        K key = e.getKey();
        V value = e.getValue();
        sb.append(key   == this ? "(this Map)" : key);
        sb.append('=');
        sb.append(value == this ? "(this Map)" : value);
        if (! i.hasNext())
            return sb.append('}').toString();
        sb.append(", ");
    }
}

You can just change the = to :.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243