Search code examples
androidkotlinsortingarraylistjvm-arguments

Order ArrayList with Int and String in Kotlin


I have the given array

val things = arrayOf<Any>("Jack", 8, 2, 6, "King", 5, 3, "Queen", "Jack");

Below is the code I have used

 things.set(things.indexOf("Jack"), 11);
  things.set(things.indexOf("Queen"), 12);
  things.set(things.indexOf("King"), 13);
  things.sort();
    
    things.set(things.indexOf(11), "Jack"));
    things.set(things.indexOf(12), "Queen");
    things.set(things.indexOf(13), "King");
    things.joinToString(":");
    things.forEach { System.out.print(it) }

Here is the error I keep getting


Unexpected tokens (use ';' to separate expressions on the same line)
Expecting an element

After removing the trailing bracket, I now get the following error

Exception in thread "main" java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')
 at java.lang.String.compareTo (:-1) 
 at java.util.ComparableTimSort.binarySort (:-1) 
 at java.util.ComparableTimSort.sort (:-1) 

Solution

  • You've 2 Jack in your list, so when you use indexOf(), it returns the index of the first occurrence of that item.

    things.set(things.indexOf("Jack"), 11);
    things.set(things.indexOf("Queen"), 12);
    things.set(things.indexOf("King"), 13);
    

    This changes your list to

    [11, 8, 2, 6, 13, 5, 3, 12, Jack]

    Now, when you apply the sort() operation on things. It throws ClassCastException on Jack as it's a string, not an int.


    To find all the indexes of a value, so you can replace them, you can create an extension function that returns a list of all the indices for a value.

    fun <T> Array<T>.indexesOfAll(predicate: (T) -> Boolean): List<Int> {
        return mapIndexedNotNull { index, any ->
            index.takeIf {
                predicate(any)
            }
        }
    }
    

    Now, you can use this indexesOfAll function to get the indexes of all the items for a particular condition.

    things.indexesOfAll { it == "Jack" }.forEach {
        things.set(it, 11)
    }
    

    You can do the same for all other values too.