강필재
강필재

Reputation: 13

How to override toString in Map...?

package A;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;

class MapManager {
    static Map<String, Double> readData(String str){
        
        Map<String, Double> map = new TreeMap<String, Double>();
        try {
             BufferedReader br = new BufferedReader(new FileReader(str));
             while(true) {
                 String line = br.readLine();
                 if(line == null) break;
                 String []sr = line.split(" ");
                 double num = Double.parseDouble(sr[1]);
                 map.put(sr[0], num);
                 }
                 br.close();
                 
             }catch(IOException e) {
                 e.printStackTrace();
             }
        
        return map;
    }
}


public class A {
    public static void main(String args[]) {
        Map<String, Double> map = MapManager.readData("input.txt");
        if(map == null) {
            System.out.println("Input file not found.");
            return;
        }
        System.out.println(map);
    }
}

output on screen is :

... But I want to make :

...

My professor said "You have to override toString in Class Map" but Map is interface then how can override tostring in Map..? And I can't modify public class A. If there are some idea that can make result that I want, please let me know:))

Upvotes: 1

Views: 964

Answers (3)

Nikolas
Nikolas

Reputation: 44368

Other answers here omit the implementation of the overriden toString method. Here they are:

// Java 8 way
@Override
public String toString() {
    return entrySet().stream()
                     .map(e -> e.getKey() + " " + e.getValue())
                     .collect(Collectors.joining());
}
// general way (preferable for this use case IMHO)
@Override
public String toString() {
    StringBuilder sb = new StringBuilder();
    forEach((key, value) -> sb.append(key).append(" ").append(value));
    return sb.toString();
}

Now, the only thing you need to decide whether you want to have a reusable class with such overriden toString method or just for one time use.

Class way

public class PrintableTreeMap<K, V> extends TreeMap<K, V> {

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        forEach((key, value) -> sb.append(key).append(" ").append(value));
        return sb.toString();
    }
}
Map<String, Double> map = new PrintableTreeMap<>();

One time use way

Map<String, Double> map = new TreeMap<>() {

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        forEach((key, value) -> sb.append(key).append(" ").append(value));
        return sb.toString();
    }
};

Upvotes: 0

TimonNetherlands
TimonNetherlands

Reputation: 1053

This is the easiest way:

TreeMap<String, Double> map = new TreeMap<String, Double>(){
    @Override
    public String toString() {
        return "override here";
    }
};

Upvotes: 2

Gaurav Jeswani
Gaurav Jeswani

Reputation: 4582

Map is reference, while in your case Object is TreeMap. So you would need to override toString() in TreeMap<K, V> class. And use CustomTreeMap rather than TreeMap compared to current code. As below :

public class CustomTreeMap<K, V> extends TreeMap<K, V> {
    private static final long serialVersionUID = 1L;

    public String toString() {
         // Your implementation goes here
    }
}

From the AbstractMap class, the default toString() implementation is below. You can manipulate this code to get desired output.

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(',').append(' ');
        }
    }

Here in your case you can also make some use of Java 8, rather than the Iterator directly.

Upvotes: 1

Related Questions