简体   繁体   中英

Sorting an array (Object[]) consisting of integers and strings - Java

I have and array of type Object[], containing integers and strings (single letters).

Object[] myArray = {(String) "U", (String) "U", (int) 2, (String) "X", (int) 4, (String) "U"};

What my question is, is there a simple way to sort this array, firstly by ints before strings and secondly by ints in numerical ascending order and string in alphabetical order? I was looking for something similar to the Arrays.sort method, but i don't think it will be that simple.

Thank you

One way would be to provide a Comparator<Object> instance and check the type of the objects to determine their sorting:

Arrays.sort(myArray, new IntStringComparator());

//...

public static class IntStringComparator implements Comparator<Object> {

    @Override
    public int compare(Object o1, Object o2) {
        if (o1 == null) {
            return -1; // o1 is null, should be less than any value 
        }
        if(o2 == null){
            return 1; // o2 is null, should be less than any non-null value
        }
        if (o1 instanceof Integer) {
            if (o2 instanceof Integer) {
                return Integer.compare((int) o1, (int) o2); // Compare by int
            } else {
                return -1; // int < String
            }
        } else {
            if (o2 instanceof String) {
                return ((String) o1).compareTo((String) o2); // Compare by string
            } else {
                return 1; // String > int
            }
        }
    }
}

Outputs:

[2, 4, U, U, U, X]

In Java 8:

    Object[] myArray = {(String) "U", (String) "U", (int) 2, (String) "X", (int) 4, (String) "U"};
    Stream.of(myArray).filter(x -> !(x instanceof String))
            .sorted().forEach(System.out::print);
    Stream.of(myArray).filter(x -> x instanceof String)
                        .sorted().forEach(System.out::print);

For David Wallace: in case you want to save the sorted array (I save it to List in this example but it can be converted into .toArray() if you want):

    Object[] myArray = {(String) "U", (String) "U", (int) 2, (String) "X", (int) 4, (String) "U"};
    List<Object> newList = Stream.of(myArray).filter(x -> x instanceof String)
                        .sorted().collect(Collectors.toList());
    Collections.addAll(newList, Stream.of(myArray).filter(x -> !(x instanceof String))
            .sorted().toArray());

    for (Object o : newList) {
        System.out.print(o);
    }

OUTPUT (of both code snippets):

24UUUX

That said, it's a bad practice to mix different types in the same array (to use Object like you did). Different types should be "mixed" only if they have an interface in common (or, if one of them extends the other )!

You can specify the function to use to compare objects, and so make it behave however you like. For an example, see Java - How can I most-efficiently sort an array of SomeClass objects by a String field in those objects?

I think the best way to go is to create a Generic Class which will implement the Comparable interface. Such that you can store any type in a Array and having a compare method to do what ever you want.

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