简体   繁体   中英

Can I sort an arraylist that is contained inside a hashmap (T)?

I have a hashmap, and it holds Key - String Type - Array of cheese objects:

public void testing(){
    HashMap<String, ArrayList<cheese>> one = new HashMap<>();
    ArrayList<cheese> two = new ArrayList<>();

    cheese seven = new cheese("59");
    cheese eight = new cheese("60");
    cheese nine = new cheese("12");
    cheese ten = new cheese("15");

    two.add(seven);
    two.add(eight);
    two.add(nine);
    two.add(ten);

    one.put("hello", two);

}

This is my cheese class:

public class cheese {

    String num;

    public cheese(String num){
        this.num = num;
    }


    public String getString(){
        return num;
    }
}

I want to get the ArrayList and sort each element inside the ArrayList, then put the objects back into the hash map.

This is java.I know it already sounds crazy but interesting too!

I thought about using Comparators, and TreeMaps but they seem like they wouldn't suit this problem. Any pointers would be helpful.

What you might want to do is extending your Cheese class to implement the Comparable<Cheese> interface.

But this assumes that your Cheese instances can constitute a total order. If you don't know what is a total order I would suggest learn more about ordering first.

The basic features that your comparable class should possess:

  • Reflexivity
  • Anti-symmetry
  • Transitivity

You can read more about this at the following link: http://algs4.cs.princeton.edu/21elementary/

Basically when your Cheese class implements the Comparable interface it inherits the method public int compareTo(T o); . You have to implement this method and return a negative integer or 0 or a positive integer based on the state of your Cheese instance according that the compared Cheese instance is smaller or equal or bigger in your total ordering.

If you only have one instance field in Cheese like in your example, that is the num field you can write something along these lines:

public class Cheese implements Comparable<Cheese> {

    String num;

    public Cheese(String num){
        this.num = num;
    }

    public String getString(){
        return num;
    }

    public int compareTo(Cheese that) {
        return this.num.compareTo(that.num);
    }
}

Note that this is a somewhat degenerate (or lucky?) case, since the state of your Cheese class depends only on a single String . So in this case deciding which one is smaller, equal or bigger can be easily done by comparing the num field. On the other hand if you later extend your class with other fields, then you should be prepared to modify your compareTo method to take those fields also into account and keep the class follow the features of total ordering.

One good practice to keep your class under control to write unit tests for all 3 features (reflexivity, anti-symmetry, transitivity) which will fail when you add new fields and your compareTo method violates total ordering.

Also if you have a single String field than I would also consider using strings to represent cheese.

Probably sorting doesn't work for you because your class didn't implement Comparable before.

As an alternative to the Comparable , you might also want to implement the Comparator interface, in this way you can detach the different cheese sorting strategies from the actual Cheese class.


EDIT: showing how to accomplish your goal

So you say that

I want to get the ArrayList and sort each element inside the ArrayList, then put the objects back into the hash map

Then you can do it like this (using my Cheese class above):

public void testing(){
        HashMap<String, List<Cheese>> one = new HashMap<>();
        List<Cheese> two = new ArrayList<>();

        Cheese seven = new Cheese("59");
        Cheese eight = new Cheese("60");
        Cheese nine = new Cheese("12");
        Cheese ten = new Cheese("15");

        two.add(seven);
        two.add(eight);
        two.add(nine);
        two.add(ten);

        System.out.println(two);
        assert "59".equals(two.get(0).num);
        assert "60".equals(two.get(1).num);
        assert "12".equals(two.get(2).num);
        assert "15".equals(two.get(3).num);

        Collections.sort(two);

        System.out.println(two);
        assert "12".equals(two.get(0).num);
        assert "15".equals(two.get(1).num);
        assert "59".equals(two.get(2).num);
        assert "60".equals(two.get(3).num);
        one.put("hello", two);
}

You can simply get an array from the hashMap and sort it using Arrays.sort. No need to put it back, the hashmap already has a reference. Using a treeset instead of array would remove the need for sorting each time an element is added. A treeset is a Set so duplicates would not be allowed if that is an issue.

I assume you've provided a minimal example. Otherwise you could just have sorted the list before putting it into the Map .

With that said, you can change mutable value types directly in a Map without any issues.

So code like the following is perfectly fine:

Map myMap = one.get("hello");
sortMyMap(myMap);

This will result in the list inside the map to be sorted (assuming that sortMyMap sorts the element in place).

If the value element in the map is immutable, you can just overwrite it with a new put :

Map myMap = one.get("hello");
Map mySortedMap = sortMyMap(myMap);
one.put("hello", mySortedMap);

Note that in this example, I assume that sortMyMap creates a new, sorted, map that it returns.

There. These 2 lines will sort all your ArrayLists .

for(String key: one.keySet()) {
    Collections.sort(one.get(key));

It's a one liner:

one.values().forEach(l -> l.sort(Comparator.comparing(cheese::getString)));

This means, invoke sort() on each List<cheese> stored as a value in the map named one , using the result of the cheese object's getString() method to order the list elements.

you can implement Comparator in you Cheese class like:

public class Cheese implements Comparator<Cheese>{

String num;

public Cheese(String num){
    this.num = num;
}

public Cheese() {

}

public String getCheese(){
    return num;
}

@Override
public int compare(Cheese o1, Cheese o2) {

    return o1.getCheese().compareTo(o2.getCheese());
}

and then in your testing() method, before - one.put("hello", two); you can write

Collections.sort(two, new Cheese());
one.put("hello", two);

I think you'll get your sorted ArrayList inside the HashMap. Hope this helps.

The answer, thanks guys;

public class one {

public void testing(){
    HashMap<String, ArrayList<cheese>> one = new HashMap<>();
    ArrayList<cheese> two = new ArrayList<>();

    two.add(new cheese("59"));
    two.add(new cheese("70"));
    two.add(new cheese("65"));
    two.add(new cheese("25"));
    one.put("hello", two);

    System.out.println(one.get("hello"));

    Collections.sort(two, new Comparator<cheese>() {

        @Override
        public int compare(cheese o1, cheese o2) {
            // TODO Auto-generated method stub
            return o1.getCheese().compareTo(o2.getCheese());
        }

    });

    System.out.println(one.get("hello"));
}

public String RemovingThe(){

    String tmp = "^(?:The)\\s(.+)$";

    Pattern a = Pattern.compile(tmp);
    Matcher b = a.matcher(" he cat in the hat");


    if(b.find()){
    return b.group(1);
    }else{
    String nop = "no";
    return nop;

    }


}

public static void main (String args[]){
    one two = new one();
    two.testing();
    System.out.println(two.RemovingThe());
    }
}

\\\\\\\\\\\\\\\\\\\\onetwothree//////////////////

public class cheese{

String num;

public cheese(String num){
    this.num = num;
}


public String getCheese(){
    return num;
}

public String toString(){
    return num;
}

public void setCheese(String num){
    this.num = num;
}



}

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