Search code examples
javaassociative-arrayjava-6

How in Java do I create an associative array structure and sorted, while keeping duplicate keys with different values pairs


Two comma separated strings exist.

The first string is essentially the keys and the second is the linked values,

The first string needs to be in ascending order while retaining any duplicate values, and the second string needs to follow in suit to maintain the sequence as such.

Looked at hashmaps and tuples without success so far. System is Java 6

String A = "3, 4, 1, 2, 3"
String B = "19, 24, 32, 68, 50"

Result Output needed

String A = "1, 2, 3, 3, 4"
String B = "32, 68, 19, 50, 24"

Solution

  • You have a multitude of possibilities to realize your requirements. Here are two examples (existing in parallel within the example code):

    1. You can use a Map<Integer, List<Integer>> that holds a key and all values it has in a List
    2. you can create a POJO class that holds exactly one key and one value, but you need to make it sortable/comparable and use a suitable data structure

    See this example and pay attention to the code comments:

    public class StackoverflowMain {
    
        public static void main(String[] args) {
            String a = "3, 4, 1, 2, 3";
            String b = "19, 24, 32, 68, 50";
    
            // Map-approach: use a map that maps a key to a list of values
            Map<Integer, List<Integer>> ab = new TreeMap<>();
            // Pair-approach: make a sortable POJO that holds a key and a value only
            // and create a data structure that holds them sorted
            SortedSet<Pair> pairList = new TreeSet<Pair>();
    
            // split both Strings by comma
            String[] aSplit = a.split(",");
            String[] bSplit = b.split(",");
    
            // check if the length of the resulting arrays is the same
            if (aSplit.length == bSplit.length) {
                // if yes, go through the arrays of numbers
                for (int i = 0; i < aSplit.length; i++) {
                    int key = Integer.parseInt(aSplit[i].trim());
                    int value = Integer.parseInt(bSplit[i].trim());
    
                    // in the Pair-approach, you just have to create a Pair with the value found
                    Pair pair = new Pair(key, value);
                    // and add it to the set of pairs
                    pairList.add(pair);
    
                    // the following check is only needed for the Map-solution
                    if (ab.containsKey(key)) {
                        // if the key is already present,
                        // just add the new value to its value list
                        ab.get(key).add(value);
                        // sort the value list each time a new value has been added
                        ab.get(key).sort(Comparator.naturalOrder());
                    } else {
                        // if the key is not present in the Map so far,
                        // create a new List for the value
                        List<Integer> valueList = new ArrayList<>();
                        // add the value to that list
                        valueList.add(value);
                        // and put both into the Map
                        ab.put(key, valueList);
                    }
                }
            } else {
                System.err.println("The Strings have different amounts of elements!");
            }
    
            // print what's in the Map
            System.out.println("Map-approach:");
            for (int key : ab.keySet()) {
                List<Integer> value = ab.get(key);
                for (int val : value) {
                    System.out.println(key + " : " + val);
                }
            }
    
            System.out.println("————————————————");
    
            System.out.println("Pairs-approach:");
            for (Pair pair : pairList) {
                System.out.println(pair.key + " : " + pair.val);
            }
        }
    
        /**
         * This class is needed for the Pair-approach.
         * It is comparable (and by that, sortable) and will be sorted by key
         * and if the keys are equal, it will sort by value.
         */
        static class Pair implements Comparable<Pair> {
            int key;
            int val;
    
            Pair(int key, int value) {
                this.key = key;
                this.val = value;
            }
    
            @Override
            public int compareTo(Pair otherPair) {
                if (key == otherPair.key) {
                    if (val == otherPair.val) {
                        return 0;
                    } else if (val < otherPair.key) {
                        return -1;
                    } else {
                        return 1;
                    }
                } else if (key < otherPair.key) {
                    return -1;
                } else {
                    return 1;
                }
            }
        }
    }
    

    This code produces the following output:

    Map-approach:
    1 : [32]
    2 : [68]
    3 : [19, 50]
    4 : [24]
    ————————————————
    Pairs-approach:
    1 : 32
    2 : 68
    3 : 19
    3 : 50
    4 : 24
    

    EDIT

    Since the Pair-approach does not sort correctly, I came up with this Map-approach:

    public class StackoverflowMain {
    
        public static void main(String[] args) {
            String a = "3, 4, 1, 3, 3, 2, 3";
            String b = "5, 24, 35, 99, 32, 68, 19";
    
            // Map-approach: use a map that maps a key to a list of values
            Map<Integer, List<Integer>> ab = new TreeMap<>();
    
            // split both Strings by comma
            String[] aSplit = a.split(",");
            String[] bSplit = b.split(",");
    
            // check if the length of the resulting arrays is the same
            if (aSplit.length == bSplit.length) {
                // if yes, go through the arrays of numbers
                for (int i = 0; i < aSplit.length; i++) {
                    int key = Integer.parseInt(aSplit[i].trim());
                    int value = Integer.parseInt(bSplit[i].trim());
    
                    // the following check is only needed for the Map-solution
                    if (ab.containsKey(key)) {
                        // if the key is already present, just add the new value to its value list
                        ab.get(key).add(value);
                        // sort the value list each time a new value has been added
                        ab.get(key).sort(Comparator.naturalOrder());
                    } else {
                        // if the key is not present in the Map so far, create a new List for the value
                        List<Integer> valueList = new ArrayList<>();
                        // add the value to that list
                        valueList.add(value);
                        // and put both into the Map
                        ab.put(key, valueList);
                    }
                }
            } else {
                System.err.println("The Strings have different amounts of elements!");
            }
    
            // print what's in the Map
            System.out.println("Map-approach:");
            for (int key : ab.keySet()) {
                List<Integer> value = ab.get(key);
                for (int val : value) {
                    System.out.println(key + " : " + val);
                }
            }
        }
    }
    

    It is shorter and uses a Map<Integer, List<Integer>> and sorts the List<Integer> every time a new value gets added (apart from the first value, which doesn't need a sort). That needed another loop in the output code, but you don't have to create a new class.

    It produces the following output:

    Map-approach:
    1 : 35
    2 : 68
    3 : 5
    3 : 19
    3 : 32
    3 : 99
    4 : 24