简体   繁体   中英

Use of a 2D HashMap

I have a text file as input and I am trying to find the number of times every word of the file appears as well as how many times it appears on each line. So for the word "banana" I would like an output like: {banana: 5,0,0,1,1,1} meaning that "banana" appears 5 times in the text, 2 times in the first line (0) and 3 times in the second line.

I am thinking of using a 2D HashMap for that so that:

Map<String, Map<Integer, Integer>> 

where String is the word, the first Integer is the line the word appears at, and the second Integer the number of occurrences in the line. The problem is that I cannot implement my idea in code as I get many errors:

Map<Map<Integer,Integer>, String > hashOfHash = new HashMap<Map<Integer, Integer>, String>();


    while (line!=null){
        Map<Integer, Integer> hash = new HashMap<Integer, Integer>();
        String[] words = line.split(" ");

        for (String z:words){
                if (hashOfHash.containsKey(z)) {
                    Integer r = hashOfHash.get(z);
                    r = r + 1;
                } else {
                    hash.put(z, new Integer(1));
                }           
        }

    }

Could anyone please assist me with the problem?

I would make a class that wraps your functionality for you:

public class WordInfo {

    private int occurrences = 0; //Store total occurances
    private final Map<Integer, Integer> lines = new TreeMap<>(); //Map line numbers to occurance counts

    public void markLine(int line) {
        Integer curr = this.lines.get(line);
        if (curr == null) {
            curr = 0;
        }
        this.lines.put(line, ++curr);
    }

    public int getOccurrences() {
        return this.occurrences;
    }

    public int getOccurrencesAtLine(int line) {
        return this.lines.containsKey(line) ? this.lines.get(line) : 0;
    }

    public Map<Integer, Integer> getOccurrenceLocations() {
        return Collections.unmodifiableMap(this.lines);
    }

}

Then it simply becomes a matter of managing your own mapping to this class appropriately (some example methods):

private final Map<String, WordInfo> wordInfo = new HashMap<>(); //Use to retrieve info about words

private WordInfo getInfo(String word) {
    WordInfo back = this.wordInfo.get(word);
    if (back == null) {
        back = new WordInfo();
        this.wordInfo.put(word, back);
    }
    return back;
}

public void markWord(String word, int line) { //Call upon occurance of a word
    this.getInfo(word).markLine(line);
}

You're working in a language which is essentially all object-orientated, it helps to make objects which represent your information rather than combining confusing amounts of Collections and Maps.

As for your specific example, you could easily convert to a string like so:

public String wordInfo(String word) {
    StringBuilder sb = new StringBuilder("{");
    WordInfo info = this.getInfo(word);
    sb.append(word).append(": ").append(info.getOccurrences());
    info.getOccurrenceLocations().entrySet().forEach(ent -> {
        for (int i = 0; i < ent.getValue(); i++) { //#getValue() -> occcurences at a line
            sb.append(",").append(ent.getKey()); //#getKey() -> line number
        }
    });
    return sb.append("}").toString();
}

Would output like

{banana: 0} //no occurrences
{banana: 1,1} //one occurrence on line 1
{banana: 5,0,0,1,1,1} //5 occurrences, 2 on line "0", 3 on line "1"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM