user3079061
user3079061

Reputation: 229

Java - Map<String, Integer> converted to Object[], how to sort

I have finally gotten my code to where it works. Although it isnt the easiest to read. I am reading from a text file that has

Date/time Tip from xxx
tip    totalAmount

My code now takes the amount tipped by a person and adds them together. eg X tip 10, X tip 20, X tip 30, Y tip 200, Z tip 30, Z tip 40 and outputs

X=60
Y=200
Z=70

I did this by turning my Map< String,Integer> into an Object[] tipsPerPerson

So how would I go about sorting this Object[] tipsPerPerson into something a bit easier to read (theres over 2000 names) a bit like this

Y=200
Z=70
X=60

Here is a portion of the code that im stuck at

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;

public class Tip {

public static void main(String[] args)
{
    int lineNumber = 1;
    Map<String, Integer> tipsByName = new HashMap<String, Integer>();
    String fileName = "C:\\Users\\David\\Desktop\\tips.txt";

    System.out.println("Reading text from file");

    try {
        FileReader inputFile = new FileReader(fileName);
        BufferedReader bufferedReader = new BufferedReader(inputFile);
        String line;
        String currentTipper = null;

        while ((line = bufferedReader.readLine()) != null) {
            if (lineNumber % 2 != 0) {
                final String tipperName = line.substring(line.indexOf("from ") + 5);
                currentTipper = tipperName;
            } else {
                final Integer tipValue = Integer.parseInt(line.substring(0, line.indexOf("\t")));
                // here we store the tip in the map. If we have a record we sum, else 
                // we store as is
                tipsByName.put(currentTipper, (tipsByName.get(currentTipper) == null ? 0 : tipsByName.get(currentTipper))
                        + tipValue);
            }

            lineNumber++;
        }
        bufferedReader.close();
       Object[] tipsName = tipsByName.entrySet().toArray();
        for (int i = 0; i < tipsByName.size(); i++) {
            System.out.println(tipsName[i]); // output the map
        }

    } catch (Exception e) {
        System.out.println("Error while reading file line by line: " + e.getMessage());
    }
   }
}

Upvotes: 0

Views: 500

Answers (3)

Bohemian
Bohemian

Reputation: 425188

Just dump the entries into a list and sort them using a Comparator:

List<Map.Entry<String, Integer>> entries = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
    public int compare(Map.Entry<String, Integer> a, Map.Entry<String, Integer> b) {
        return Integer.compare(b.getValue(), a.getValue());
    }
});

Note that b is compared to a, rather than the other way around, to give us reverse order (largest to smallest).

All done in two lines. If you then iterate over the list, it will be in the order you wanted. Use getKey() and getValue() to print, or simply use the default toString() of the Entry:

for (Map.Entry<String, Integer> entry : entries)
    System.out.println(entry + '\n');

Upvotes: 1

Elliott Frisch
Elliott Frisch

Reputation: 201467

Ouch. Don't do that! Try this instead...

// Get the Entries.
java.util.Set<Entry<String, Integer>> entrySet = tipsByName
    .entrySet();
// Make a SortedSet with a Custom Comparator.
SortedSet<Entry<String, Integer>> sortedSet = new TreeSet<Entry<String, Integer>>(
    new Comparator<Entry<String, Integer>>() {
      public int compare(
          Entry<String, Integer> o1,
          Entry<String, Integer> o2) {
        if (o1 == o2) {
          return 0;
        } else if (o1 == null) {
          return -1;
        } else if (o2 == null) {
          return 1;
        }
        return o1.getValue().compareTo(
            o2.getValue());
      }
    });
// Add the Entries to the SortedSet.
for (Entry<String, Integer> entry : entrySet) {
  sortedSet.add(entry);
}

// Iterate the sortedSet.
Iterator<Entry<String, Integer>> iter = sortedSet
    .iterator();

while (iter.hasNext()) {
  System.out.println(iter.next()); // print your sorted items.
}

Upvotes: 0

Diversity
Diversity

Reputation: 1900

An advice: use the map and d'ont make any array convertions. The map class gives you all that you need. You can iterate over the keys or over the values or over both like you do right now.

Just use the key values of your map and pass it as an argument to Collections.sort(). This works because the returned key set is of type Collection which can be passed to the Collections.sort() method.

Than it will be ordered in alphabetical order. If you want something else just pass an additonal Comparator class to the Collection.sort() or wrap your object within a customized class which implements the interface Comparable.

After that you just iterate throught you keys and invoke map.get(key) method.

Example:

Iterator<String> sortedKeys = map.keySet().iteator();
for (String key :keys) {

  sysout(key: "+key+" value : "+ map.get(key));
}

Hope it was thge answer you needed.

Upvotes: 0

Related Questions