I have a mutableListOf<MutableList<Int>> in kotlin. How do I pop the last element out of this list?
I have tried removeAt but it didn't work.
fun main() {
val intervals:List<List<Int>> = listOf(listOf(2,9), listOf(1,8), listOf(-4, 234), listOf(22,1))
println(intervals)
var sortedIntervals = intervals.toMutableList().sortedWith(Comparator<List<Int>>
{a, b -> a[0].compareTo(b[0])})
println(sortedIntervals)
sortedIntervals = sortedIntervals.map() {it -> it.toMutableList()}
println(sortedIntervals.last())
sortedIntervals.removeAt(sortedIntervals.size-1)
println(sortedIntervals)
}
You can use removeLastOrNull() or removeLast() functions:
// sortedIntervals must be MutableList to call removeLastOrNull() or removeLast()
val sortedIntervals: MutableList<...> = ...
sortedIntervals.removeLastOrNull()
The difference between them is that removeLast() function throws NoSuchElementException if this list is empty, but removeLastOrNull() doesn't throw an exception, it returns null if this list is empty.
Related
I try to make a variable sized immutable list in Kotlin, but the only way I found is this. Isn't there a more clean way to do it ?
val size = nextInt(0, 50)
val list = mutableListOf<Post>()
for (i in 0..size) {
list.add(getRandomPost())
}
val immutableList = Collections.unmodifiableList(list)
When my source is another list (with random size) I can do val immutableList = otherList.map{ /* thing that will be add() */ } but found nothing similar for just integrer
U can benefit on kotlin collections extensions and use List builder
val list: List<Post> = List(Random.nextInt(0, 50)) {
getRandomPost()
}
I assign the onValue to two variables in initState.
_boc.selectList(locationId).then((onValue) {
list = onValue;
filterList = onValue;
setState(() {});
});
When it comes to this function, I clear the filterList, but the length of the list become 0.
Future<List<Obk>> getSuggestion(
String search) async {
if (search == "empty") return [];
if (search == "error") throw Error();
filterList.clear();
print(list.length); // this print 0
});
...
}
but if I remove this line filterList = onValue; , it will show the length of the list.
How to prevent the items in list from deleted?
Instead of assigned the same List Object to both list and filteredList. You can make a new list object using List.from(). So that your original List remains unchanged.
_boc.selectList(locationId).then((onValue) {
list = onValue;
filterList = List.from(onValue);
setState(() {});
});
Now if you try to run your code and print the list length then you'll not get 0 after calling filterList.clear().
Future<List<Obk>> getSuggestion(
String search) async {
if (search == "empty") return [];
if (search == "error") throw Error();
filterList.clear();
print(list.length); // this will print list length
});
...
}
I have a program that performs an:
Await.result(Processor.validateEntries(queuedEntries)), Duration.Inf)
And the validateEntries method calls some other method that performs:
val validatedEntries: ListBuffer[Entries] = new ListBuffer[Entries]
for (entry <- queuedEntries) {
checkEntry(entry.name).map(.......... validatedEntries += Entries(...) )
}
Future(validatedEntries.toList)
where checkEntry returns a Future[Boolean].
def checkEntry(name: String): Future[Boolean] = {
checkNameAlreadyExists(name).flatMap(exists =>
buildRequest(exists, name).map(response => {
if (!response.contains("error")) {
true
} else {
false
}
})
)
}
At the top level where I perform the Await.result I also get back an empty list: List(). Any suggestions would greatly help!
Mixing mutable collections and concurrency is not a good idea. Consider refactoring checkEntry to return, say, Future[Option[Entry]] instead of Future[Boolean], where Some would represent successful validation, whilst None unssucessful, and then you might do something like
case class Entry(v: Int)
val queuedEntries = List(Entry(1), Entry(2), Entry(3))
def checkEntry(entry: Entry): Future[Option[Entry]] = ???
Future
.traverse(queuedEntries)(checkEntry)
.map(_.flatten)
If keeping checkEntry as it is, then you might try something like
case class Entry(v: Int)
val queuedEntries = List(Entry(1), Entry(2), Entry(3))
def checkEntry(entry: Entry): Future[Boolean] = Future(Random.nextBoolean)
Future
.traverse(queuedEntries)(checkEntry)
.map(checkedEntries => checkedEntries zip queuedEntries)
.map(_.collect { case (validated, entry) if validated => entry} )
You have to use for comprehension. Basically first you have to read the list and in yield, you have to call function one by one and wait for future to complete by yield
package com.vimit.StackOverflow
import scala.concurrent._
import ExecutionContext.Implicits.global
object FutureProblem extends App {
val list = List(1, 2, 3)
val outputList = List()
val result = for {
value <- list
} yield {
for {
result <- getValue(value).map(res => outputList ++ List(value))
} yield result
}
print(result)
def getValue(value: Int) = Future(value)
}
I'm trying to add an element list to the list of string, but I found Kotlin does not have an add function like java so please help me out how to add the items to the list.
class RetrofitKotlin : AppCompatActivity() {
var listofVechile:List<Message>?=null
var listofVechileName:List<String>?=null
var listview:ListView?=null
var progressBar:ProgressBar?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_retrofit_kotlin)
listview=findViewById<ListView>(R.id.mlist)
var apiInterfacee=ApiClass.client.create(ApiInterfacee::class.java)
val call=apiInterfacee.getTaxiType()
call.enqueue(object : Callback<TaxiTypeResponse> {
override fun onResponse(call: Call<TaxiTypeResponse>, response: Response<TaxiTypeResponse>) {
listofVechile=response.body()?.message!!
println("Sixze is here listofVechile ${listofVechile!!.size}")
if (listofVechile!=null) {
for (i in 0..listofVechile!!.size-1) {
//how to add the name only listofVechileName list
}
}
//println("Sixze is here ${listofVechileName!!.size}")
val arrayadapter=ArrayAdapter<String>(this#RetrofitKotlin,android.R.layout.simple_expandable_list_item_1,listofVechileName)
listview!!.adapter=arrayadapter
}
override fun onFailure(call: Call<TaxiTypeResponse>, t: Throwable) {
}
})
}
}
A more idiomatic approach would be to use MutableList instead of specifically ArrayList. You can declare:
val listOfVehicleNames: MutableList<String> = mutableListOf()
And add to it that way. Alternatively, you may wish to prefer immutability, and declare it as:
var listOfVehicleNames: List<String> = emptyList()
And in your completion block, simply reassign it:
listOfVehicleNames = response.body()?.message()?.orEmpty()
.map { it.name() /* assumes name() function exists */ }
Talking about an idiomatic approach... 🙄
When you can get away with only using immutable lists (which means usually in Kotlin), simply use + or plus. It returns a new list
with all elements of the original list plus the newly added one:
val original = listOf("orange", "apple")
val modified = original + "lemon" // [orange, apple, lemon]
original.plus("lemon") yields the same result as original + "lemon". Slightly more verbose but might come in handy when combining several collection operations:
return getFruit()
.plus("lemon")
.distinct()
Besides adding a single element, you can use plus to concatenate a whole collection too:
val original = listOf("orange", "apple")
val other = listOf("banana", "strawberry")
val newList = original + other // [orange, apple, banana, strawberry]
Disclaimer: this doesn't directly answer OP's question, but I feel that in a question titled "How to add an item to a list in Kotlin?", which is a top Google hit for this topic, plus must be mentioned.
If you don't want or can't use array list directly use this code for add item
itemsList.toMutableList().add(item)
itemlist : list of your items
item : item you want to add
instead of using a regular list which is immutable just use an arrayListof which is mutable
so your regular list will become
var listofVehicleNames = arrayListOf("list items here")
then you can use the add function
listOfVehicleNames.add("what you want to add")
you should use a MutableList like ArrayList
var listofVechileName:List<String>?=null
becomes
var listofVechileName:ArrayList<String>?=null
and with that you can use the method add
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/add.html
For any specific class, the following may help
var newSearchData = List<FIRListValuesFromServer>()
for (i in 0 until this.singleton.firListFromServer.size) {
if (searchText.equals(this.singleton.firListFromServer.get(i).FIR_SRNO)) {
newSearchData.toMutableList().add(this.singleton.firListFromServer.get(i))
}
}
val listofVechile = mutableListOf<String>()
Declare mutable list like that and you will be able to add elements to list :
listofVechile.add("car")
https://kotlinlang.org/docs/collections-overview.html
I am writing a JUnit test case for a method that leads me to another method that is default, it returns a new ArrayList when that default method is called.
Test method
public List getTagDataForImage(String tagType, String imageType) {
List tagRules = getTagRulesForUpdateOrQueryImage(tagType, imageType);
List tagData = getTagData(tagRules);
return tagData;
}
In the method the stack trace points me to getTagRulesForUpdateOrQueryImage(tagType, imageType); which leads me here
List getTagRulesForUpdateOrQueryImage(String tagType, String imageType) {
List commonList = tagList.getTagRulesForUpdateOrQueryImage(tagType
+ "," + imageTypes[0]); //This line
commonList.addAll(tagList.getTagRulesForUpdateOrQueryImage(tagType
+ "," + imageType));
return commonList;
}
definition for tagList.getTagRulesForUpdateOrQueryImage(tagType
+ "," + imageTypes[0]); defined in another class
List getTagRulesForUpdateOrQueryImage(String tagType) {
return new ArrayList((List) tagRulesMap.get(tagType));//gives NPE
}
tagRulesMap is a HashMap that is populated automatically at constructor call
Test case
#InjectMocks
TagDataFilter tagDataFilter;
#Test
public void testGetTagDataForImage()
{
List get=tagDataFilter.getTagDataForImage("QueryImages", "Common");
}
Stack Trace
java.lang.NullPointerException
at java.util.ArrayList.<init>(Unknown Source)
at data.TagList.getTagRulesForUpdateOrQueryImage(TagList.java:107)
at data.TagDataFilter.getTagRulesForUpdateOrQueryImage(TagDataFilter.java:92)
at data.TagDataFilter.getTagDataForImage(TagDataFilter.java:73)
at data.test.TagDataFilterTest.testGetTagDataForImage(TagDataFilterTest.java:54)
I am not able to figure out where I have gone wrong.Please help me solve this problem.
Just to provide a answer from the comments:
List getTagRulesForUpdateOrQueryImage(String tagType) {
return new ArrayList((List) tagRulesMap.get(tagType));//gives NPE
}
the key tagType is not found and because of this it returns null which is then tried to cast which then returns a NullPointerException.