0

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());
    }
   }
}
3
  • is there a specific reason to convert to Object array? you could convert to Integer array and apply sort Commented Dec 14, 2013 at 5:32
  • So you want to sort the map by its values, in descending order? Commented Dec 14, 2013 at 5:44
  • Ascending or descending. Just so I dont have to go back and forth checking values and putting them in order Commented Dec 14, 2013 at 5:54

3 Answers 3

1

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');
Sign up to request clarification or add additional context in comments.

8 Comments

But hey you need a full hd screen to meet the line reqirmentes of the your definition ;-)
List<Map.Entry<String, Integer>> entries = new ArrayList<>(map.entrySet()); is a possibility for the first line if you are using 1.7.
You are absolutely amazing Bohemian!!!! Thank you so much!!!!!! I was going crazy trying to get this to work!
May I ask where you learned Java? I have been using a book but I feel as if its not teaching me too much other than basic syntax
Thank you! <blush/>. I learned java from a friend and have used it for about 15 years. I haven't read many books about it. I learned by doing. Learn the GOF patterns, and always look for ways to use the java JDK, especially Collections. Also learn regex - it can be so powerful and useful. Always look to learn from pros - read blogs, read the better answers here and similar forums, watch youtube videos from google devs and Josh Bloch. Lastly, try to answer questions here: You might be surprised at what you don't know when you try to answer, and how much you'll learn when you answer well.
|
0

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.

Comments

0

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.
}

1 Comment

Ill post the rest of my code so you can see what it is im doing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.