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?
    }
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
PAA
  • 1
  • 46
  • 174
  • 282
  • 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. – user15187356 Mar 03 '21 at 16:44
  • Yes its a print statement. Can you suggest solution or pointer? – PAA Mar 03 '21 at 16:47
  • 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. – user15187356 Mar 03 '21 at 16:47
  • Is there a relation between String and int. If so, you can use Map. Or you can use stream and map operator to transform each element to string after that you can use reduce to generate the string – JHDev Mar 03 '21 at 16:48
  • 1
    If you've already *got* an array, then use it to load a (temporary) TreeMap, and then cycle through the map in order. – user15187356 Mar 03 '21 at 16:48
  • Can anyone please show some code ? Its expected to get result like this. Bat, 2, Cat, 4, Dat, 6 like this. But this problem statement I got. Please guide – PAA Mar 03 '21 at 16:50
  • 1
    Why should the result be that? What makes "Bat, Dat, Cat, 2, 4, 6" the wrong result? – k314159 Mar 03 '21 at 16:51
  • 1
    Like i said you can use Arrays.stream to produce the output – JHDev Mar 03 '21 at 16:51

3 Answers3

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))
)
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
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.

user15187356
  • 807
  • 3
  • 3
  • @user15187356 : Juste replace for (Map.Entry e : temp) with for (Map.Entry e : temp.entrySet()) .And the code will work fine – JHDev Mar 03 '21 at 17:32
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,
Jonny Henly
  • 4,023
  • 4
  • 26
  • 43
  • You also need to check if `this.{first,last} != null && that.{first,last} == null`. – k314159 Mar 03 '21 at 18:30
  • @k314159 the `compareTo(...)` methods of `Pair.first` and `Pair.last` have the responsibility of handling a `null` argument. – Jonny Henly Mar 03 '21 at 18:51
  • 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 Mar 04 '21 at 09:09
  • 1
    @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?](https://stackoverflow.com/questions/6259354/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. – Jonny Henly Mar 04 '21 at 17:47