Best way to convert an Enumeration<String> to Array<String> in Kotlin? - kotlin

Incidentally, I have an Enumeration<String> in Kotlin. It contains toList(), but I need to convert it to an Array<String>.
What is the best way to do this in Kotlin?

Lists can be converted to arrays via the .toTypeArray function:
val myEnumeration: Enumeration<String> = ...
val array = myEnumeration.toList().toTypedArray() // array is Array<String>
A simple extension function as a shortcut is also trivial:
inline fun <reified T> java.util.Enumeration<T>.toTypedArray(): Array<T> = toList().toTypedArray()
The reason toTypedArray() doesn't work directly on an Enumeration is that it needs a Collection<T> to be able to efficiently instantiate the new array, but going through toList() first is still efficient enough for most scenarios.

Related

How to slice vararg argument

I wrote an extension function to get an element of an JSON object by its name:
fun JSONObject.obj (name: String): JSONObject? =
try { this.getJSONObject(name) }
catch (e: JSONException) { null }
Now I want to extend this for nested JSON objects. I wrote the following:
tailrec fun JSONObject.obj (first: String, vararg rest: String): JSONObject? =
if (rest.size == 0)
obj(first)
else
obj(first)?.obj(rest[0], *rest.drop(1).toTypedArray())
But this looks quite inefficient to me.
What is the best way to slice a vararg argument?
We could use vararg only in the public function, but then internally use list for recursion:
fun JSONObject.obj (first: String, vararg rest: String): JSONObject? = obj(first, rest.asList())
private tailrec fun JSONObject.obj (first: String, rest: List<String>): JSONObject? =
if (rest.size == 0)
obj(first)
else
obj(first)?.obj(rest[0], rest.subList(1, rest.size))
Both asList() and subList() don't copy data, but only wrap the existing collection. Still, this is far from ideal, because it creates a new object for each iteration and it may create a chain of views (it depends on internal implementation of subList()). Alternatively, the internal function could receive an array and offset - this will solve both above problems.
Generally, I suggest to not try turning Kotlin into something it is not. It has limited support for functional constructs, but it is not a functional language. Without the linked list implementation which could be easily split into head and tail, this style of code will be always inefficient and/or cumbersome. You can look for such implementation, for example in Arrow or kotlinx.collections.immutable. The latter has ImmutableList with optimized subList() - you can use it with the solution provided above to avoid creating a chain of lists.
Update
As a matter of fact, basic lists implementations in the Java stdlib also provide optimized subList(): AbstractList.java. Therefore, the above solution using simply asList() should be fine, at least when targeting JVM.
Instead of slicing, why don't you try just iterating over all the objects and getting the JSONObjects? I think this would be much more efficient.
fun JSONObject.obj(vararg names: String): JSONObject? {
var jsonObject = this
for (name in names) {
if (!jsonObject.has(name))
return null
jsonObject = jsonObject.getJSONObject(name)
}
return jsonObject
}

How to convert ArrayList<String?> to List<CharSequence> in kotlin

I am new to kotlin and I am facing this issue
I have an ArrayList<String?> and I have to pass it to a function that accepts List<CharSequence>
I tried to find a way to convert them but couldnt, How can I convert ArrayList<String?> to List<CharSequence> in kotlin
Use
val list: List<CharSequence> = arrayList.filterNotNull()
filterNotNull() removes any possible null values so you have a List<String>, which can be automatically up-cast to a List<CharSequence>.
CharSequence is an interface and String class is already implemented that. Hence cast to CharSequence should be enough. map function returns List<T>
val list = arrayList.map { it as CharSequence }
With filtering null values
val list: List<CharSequence> = arrayList.filterNotNull()

How to initialize List< List<Int> > in Kotlin?

As per leetcode question here I am required to return List<List<Int>> type for Kotlin submission.
I tried using listOf() but unable to create.
My another guess was to use LinkedList of type List:
var result: List<List<Int>> = LinkedList<List<Int>>()
The intelliJ idea gives no warnings for the above declaration but add() is not available on result variable. Please let me know what I am doing wrong.
How should I initialize empty List<List<Int>> type in kotlin?
add is not available for List. It's available for MutableList. LinkedList is a MutableList, but you are upcasting it to a plain List by assigning it to a variable of type List.
If you need to work with a MutableList or LinkedList inside this function, you can do so by not declaring the type of the result variable so it will implicitly be a MutableList or LinkedList. When you return it from the function, it will be implicitly upcast at that time, when you no longer need the mutable features.
fun threeSum(nums: IntArray): List<List<Int>> {
val output = mutableListOf<MutableList<Int>>()
// logic
return output
}
or
fun threeSum(nums: IntArray): List<List<Int>> {
val output = LinkedList<LinkedList<Int>>()
// logic
return output
}
LinkedList is a specific type of MutableList that compared to the default MutableList (ArrayList) is heavier and slower at accessing specific elements in the middle, but faster at accessing elements at the start/end and faster at inserting or removing elements. You will most commonly just want to use mutableListOf to instantiate mutable lists.
you can use
var result: List<List<Int>> = listOf(listOf())
or
var result = listOf(listOf<Int>())

Adding char to List<Char> in kotlin

I am trying to create List<Char> from String in Kotlin but it seems there is no inbuilt function is provided by lib. Also casting will generate error. So here is what I am doing. Please let me know if I am missing something in question. (Or we can say converting string to List<Char> in Kotlin).
var stringVal = "ABC"
var genList:List<Char> = arrayListof()
var count = 0
while (stringVal.length == genList.size) {
// way to add stringVal to genList
count++
}
The answer given by #Moira is definitely the way to go here, I would accept it.
However, the question was about adding an element to a List<Char>, which isn't possible in Kotlin because a List is immutable and yours gets initialized as an empty one, so it will stay empty.
Use a MutableList<Char> and simply add single Chars to it if you need it:
fun main(args: Array<String>) {
var genList = mutableListOf<Char>()
genList.add('a')
genList.add('A')
genList.add('B')
genList.add('C')
println(genList)
}
Output:
[a, A, B, C]
val chars = "ABC".toList()
CharSequence has a to(Mutable)List extension function defined in kotlin.text.
fun CharSequence.toList(): List<Char>
Returns a List containing all characters.
kotlin-stdlib / kotlin.text / toList
fun CharSequence.toMutableList(): MutableList<Char>
Returns a MutableList filled with all characters of this char sequence.
kotlin-stdlib / kotlin.text / toMutableList
Kotlin's standard libraries have hundreds of utility functions like this, so chances are that most of the time what you want already exists.
Many standard types that conceptually model some sort of iterable data, but are not Iterable, have extensions defined on them that are equivalent to those in kotlin.collections.

ArrayList<String>() vs arrayListOf<String>()

I was going through some Kotlin basics and found two syntaxes.
ArrayList<String>()
And
arrayListOf<String>()
What is the difference between these two as both are part of Kotlin.Collections?
arrayListOf<T>() is mainly there for your convenience. vararg-functions usually come with a (sometimes negligible) performance impact and switching between the arrayListOf(someElements...) and arrayListOf() without that convenience method would basically delegate that problem to you as a programmer. You have to know it and you would have to change that code to ArrayList(), if such an impact is affecting you and if that convenience function wouldn't exist.
arrayListOf() is basically just that. It returns ArrayList() and it is inlined. That's just convenient, so that you don't really have to think about it, when you switch back and forth between arrayListOf(someElements) and arrayListOf().
That having said: there is no difference between arrayListOf() and ArrayList() as also others have already mentioned and arrayListOf(elements) is the convenience variant to construct an ArrayList with the given elements.
arrayListOf is a function, that has optional variable length arguments
In case of using it without arguments, there is no difference
arrayListOf<T>()
is just an extension function that looks like this:
public inline fun <T> arrayListOf(): ArrayList<T> = ArrayList()
it a function is right but is use of like this
here in function used set() function of arrayListOf() is used to set the given element at specified index and replace if any element already present at that index
fun main(args: Array<String>){
val list: ArrayList<String> = arrayListOf<String>()
list.add("Ajay")
list.add("Vijay")
list.add("Prakash")
println(".......print list.......")
for (i in list) {
println(i)
}
println(".......arrayList.set(2,\"Rohan\").......")
list.set(2,"Rohan")
println(".......print ArrayList.......")
for (i in list) {
println(i)
}
}
Output
.......print list.......
Ajay
Vijay
Prakash
.......list.set(2,"Rohan").......
.......print list.......
Ajay
Vijay
Rohan
When creating an empty array, you can use either:
val emptyArray1 = ArrayList()
val emptyArray2 = arrayListOf()
But when creating an array from existing elements, you have to use one or the other depending on whether the existing elements are already in a collection or you want to specify them individually:
val arrayFromCollection = ArrayList(hashMap.keys)
val arrayFromElements = arrayListOf("1", "2", "3")
Note that you can use the spread operator to pass an existing collection into arrayListOf as individual elements, but if the collection is anything other than another array, you also need to convert it to an array. This probably isn't worth the extra verbosity:
val arrayFromCollectionVerbose = arrayListOf(*hashMap.keys.toTypedArray())