0

Sorry about the non-descriptive title, I couldn't think of a way to explain it better short of 100 words. What I would like to be able to do is sort a list of strings into "boxes" based on a string associated with the main string and an array of strings "order".

For my current setup I am using a HashMap to store the string and it's associated "place-in-the-order" string.

I am aware that my explanation is truly crap so I have made an image which I hope will explain it better:

The variables are initialised as follows:

private final String[] order = new String[] {"Severe", "Warning", "Info"};
private final Box[] boxes = new Box[] {new Box(1), new Box(2), new Box(3), new Box(4)};
private final Map<String, String> texts = new HashMap<String, String>();

texts.put("Server on fire!", "Severe");
texts.put("All is good!", "Info");
texts.put("Monkeys detected!", "Warning");
texts.put("Nuke activated!", "Severe");

No! This shouldn't be too hard to implement but the only way I can think of doing it is by using 3 loops which seems a bit wasteful and would be slow if there was large numbers of any of the inputs.

Here is some example code which will hopefully show what I have come up with so far and perhaps explain the problem, I have not tested it and don't have an IDE handy so have probably overlooked something.

Set<Box> usedBoxes = new HashSet<Box>();

for(String curOrder : order) {
    for (String text : texts) {
        if (texts.get(text).equals(order)) {
            for (Box box : boxes) {
                if (!usedBoxes.contains(box)) {
                    box.setText(text);
                    usedBoxes.add(box);
                    break;
                }
            }
        }
    }
}
user2248702
  • 2,741
  • 7
  • 41
  • 69
  • Maybe this helps: http://stackoverflow.com/questions/109383/how-to-sort-a-mapkey-value-on-the-values-in-java – Max Meijer May 31 '14 at 14:42

2 Answers2

1

I'm not sure I fully understand what you want to achieve, but I feel that there are two things that would make your design much simpler:

  1. Don't use Strings for your severity levels. Use enums instead. Enums have a name, may have other fields and methods, and are naturally ordered using their order of definition. And there is no way to make a typo and introduce an unknown severity: they're type-safe

    enum Severity {
        SEVERE, WARNING, INFO
    }
    
  2. Don't store things in parallel arrays or associate them with maps. Define a class containing the information of your objects:

    public class Box {
        private String text;
        private Severity severity;
    }
    

Now that you have these, you can simply create a List<Box>, and sort it using a Comparator<Box> which sorts them by severity, for example:

List<Box> boxes = Arrays.asList(new Box("Server is on fire", Severity.SEVERE),
                                new Box("All is good", Severity.INFO),
                                ...);
Collections.sort(boxes, new Comparator<Box>() {
    @Override
    public int compare(Box b1, Box b2) {
        return b1.getSeverity().compareTo(b2.getSeverity());
    }
}

or even simpler, with Java 8:

boxes.sort(Comparator.comparing(Box::getSeverity));
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • The reason for using severity as a string is that I want it to be customisable for the end user. – user2248702 May 31 '14 at 23:58
  • Then make it a class implementing Comparable, with a name and a rank property (the rank being the way to compare a severity to another one). – JB Nizet Jun 01 '14 at 06:07
1

You should make your "statuses" (Severe, Info etc) into an Enum.

public enum StatusLevel {
    Severe,
    Warning,
    Info;
}

You can then sort by StatusLevel natively as long as you define the in a top to bottom order.

If you want to supply your Box object directly insead of pulling out the StatusLevel or have a secondary sort by another property like time or alphabetically you should implement your own Comparator

Also you may want to look into SortedMap or other Map that keeps its order so you don't have to resort a HashMap every time as it does not guarantee order.

indivisible
  • 4,892
  • 4
  • 31
  • 50