1

I'm extending the question further here - Creating an array that stores strings and integers in java.

I'm looking to generically implement below solution.

public class Demo {
    public static void main(String[] args) {
        Object[] values = {"Cat", 4, "Bat", 2};
        
        // expected result should be => Bat, 2, Cat, 4 - Any pointers?
    }
}
8
  • 1
    What is "output" ? Is this the visible result of some sort of print statement? Then cycle through the array and print the result of calling toString on each element. Commented Mar 3, 2021 at 16:44
  • 2
    Or do you want to somehow consider the array as holding 'key1, val1, key2, val2'. And print in lexical order of keys? The first thing to say is that this is a totally inappropriate data structure for the use. Use some sort of sorted map. Commented Mar 3, 2021 at 16:47
  • 1
    If you've already got an array, then use it to load a (temporary) TreeMap, and then cycle through the map in order. Commented Mar 3, 2021 at 16:48
  • 1
    Why should the result be that? What makes "Bat, Dat, Cat, 2, 4, 6" the wrong result? Commented Mar 3, 2021 at 16:51
  • 1
    Like i said you can use Arrays.stream to produce the output Commented Mar 3, 2021 at 16:51

3 Answers 3

2

It appears that the task is about sorting the pairs of elements of the input array (however, all elements are Comparable) and it can be resolved without creating/using Pair class with the help of Stream API.

Also, the output result is also an array of objects.

Object[] values = { "Cat", 4, "Bat", 4, "Dat", 6, "Bat", 2 };

// prepare comparators
Comparator<List<Comparable>> comparator0 = Comparator.comparing(list -> list.get(0));
Comparator<List<Comparable>> comparator1 = Comparator.comparing(list -> list.get(1));

Object[] sorted = IntStream.range(0, values.length / 2)
         .mapToObj(i -> Arrays.asList((Comparable)values[2 * i], (Comparable)values[2 * i + 1]))
         .sorted(comparator0.thenComparing(comparator1))
         .flatMap(List::stream)
         .toArray(Object[]::new);

System.out.println(Arrays.toString(values));
System.out.println(Arrays.toString(sorted));

Output:

[Cat, 4, Bat, 4, Dat, 6, Bat, 2]
[Bat, 2, Bat, 4, Cat, 4, Dat, 6]

.sorted may use Comparator written in this equivalent form:

sorted((a1, a2) -> a1.get(0).compareTo(a2.get(0)) == 0 
        ? a1.get(1).compareTo(a2.get(1)) 
        : a1.get(0).compareTo(a2.get(0))
)
Sign up to request clarification or add additional context in comments.

Comments

1
Map<String,Integer> temp = new TreeMap<>();
for (int v=0; v<values.length-1; v+=2)
    temp.put((String)values[v], (Integer)values[v+1]);
for (Map.Entry<String,Integer> e : temp.entrySet())
    System.out.printf(" %s : %s ", e.getKey(), e.getValue());

Check the method names with the doc, this is off the top of my head.

1 Comment

@user15187356 : Juste replace for (Map.Entry<String,Integer> e : temp) with for (Map.Entry<String,Integer> e : temp.entrySet()) .And the code will work fine
1

Here's a version using a generic Pair<T, E> class and an ArrayList<Pair<String, Integer>> to keep with array's random access.

// entry point of the program
public static void main (String[] args) throws java.lang.Exception {
    Object[] values = { "Cat", 4, "Bat", 4, "Dat", 6, "Bat", 2 };
    
    // create the list of pairs
    List<Pair<String, Integer>> pairs = new ArrayList<>(values.length / 2);
    
    // iterate over values, construct pairs and add them to the list
    for (int i = 0, n = values.length - 1; i < n; i += 2) {
        // note that we have to cast Object to String and Integer
        pairs.add(new Pair<String, Integer>((String) values[i], (Integer) values[i + 1]));
    }
    
    // sort the list
    pairs.sort((p1, p2) -> p1.compareTo(p2));
    
    // output each pair via Pair#toString
    pairs.forEach(pair -> System.out.printf("%s, ", pair));
}
    
private static class Pair<T extends Comparable<? super T>, E extends Comparable<? super E>>
implements Comparable<Pair<T, E>>
{
    private T first;
    private E last;

    public Pair(T first, E last) {
        this.first = first;
        this.last = last;
    }

    public T getFirst() { return first; }
    public E getLast() { return last; }

    @Override
    public String toString() { return String.format("%s, %s", first, last); }

    @Override
    public int compareTo(Pair<T, E> what) {
        // throw an NPE if this.compareTo(null), per Comparable's Javadoc
        final Pair<T, E> that = Objects.requireNonNull(what);
        
        if (this == that) { return 0; }
        
        int cmpFirst = 0;
        
        // handle this.first being null
        if (this.first == null) {
            if (that.first != null) { return -1; }
        } else {
            if (that.first == null) { return 1; }
            
            cmpFirst = this.first.compareTo(that.first);
        }
        
        // handle this.first not equaling that.first
        if (cmpFirst != 0) { return cmpFirst; }
        
        // handle this.last being null
        if (this.last == null) {
            if (that.last != null) {
                return -1;
            } else {
                return 0;
            }
        }
        
        // at this point this.first == that.first and this.last != null
        return this.last.compareTo(that.last);
    }
}

Output:

Bat, 2, Bat, 4, Cat, 4, Dat, 6,

4 Comments

You also need to check if this.{first,last} != null && that.{first,last} == null.
@k314159 the compareTo(...) methods of Pair.first and Pair.last have the responsibility of handling a null argument.
The javadoc for Comparable specifies that compareTo() should throw NullPointerException if the passed object is null. So I think that means you should also throw the exception if 'this.first/second' is null. Or just check org.apache.commons.lang3.tuple.Pair and do whatever it does.
@k314159 you're correct in regard to Pair.compareTo(null), updated my code to throw an NPE. However, the Javadoc for Comparable stipulates nothing about the handling of null members, see What should int compareTo() return when the parameter string is null?. Though I think I need to update my code to ensure antisymmetry, reflexivity and transitivity.

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.