Search code examples
listkotlincomparison

Kotlin: How to check if a mutabeListOf<Pair<Object, Int>> already contains a specific Object?


I want to check if a mutableListOf<Pair<Product, Int>> already contains a product with a specific name. If there is a Pair<Product, Int> with the searched name, the Int value of this product should be increased.

Here is my approach:

fun main() {
    val item = Item()
    
    val prod1 = Product("Test")
    val prod2 = Product("Test")

    item.addProduct(prod1, 1)
    item.addProduct(prod2, 5)

   for ((prod,amount) in item) println("$Productname: {prod.productName}, $amount")
}

The Output should be:

Productname: Test, 6

and not:

Productname: Test, 1

Productname: Test, 5

Here the Product Class:

class Product(val productName: String) {
    // other stuff that is unnecessary for the question
}

And the Item Class:

class Item {
    private val pairList = mutableListOf<Pair<Product, Int>>()

    fun addProduct(product: Product, quantity: Int) {
        for (prod in pairList) {
            if (pairList.contains(Pair(product, quantity))){
                val value = prod.second + quantity
                prod.copy(second = value)
            } else {
                pairList.add(Pair(product, quantity))
            }
        }
    }
}

Currently, nothing works (neither the comparison nor adding a new Pair). I appreciate every post!


Solution

  • Here there are two possibilities depending on your needs.

    1. Use MutableMap<Product, Int>

    This is a perfect use-case to use a MutableMap<K, V> instead of MutableList<Pair<K, V>> since you need to find the current quantity for a given product and increase it:

    private val productMap = mutableMapOf<Product, Int>()
    
    fun addProduct(product: Product, quantity: Int) {
        val foundQuantity = productMap[product]
        // Increase the found quantity by [quantity] or add the given [quantity].
        val finalQuantity = foundQuantity?.let { it + quantity } ?: quantity
        productMap[product] = finalQuantity
    }
    

    To do this, you should make your Product class a data class (or implement manually equals and hashcode) to be able to compare the hash of two Products using their productName value.

    data class Product(val productName: String) { ... }
    

    The pros of this solution are the fast lookups and the fast insertions. The cons of this solution is that your products won't be sorted anymore.

    2. Use MutableList<Pair<Product, Int>>

    If you need your products sorted and you need to maintain the same insertion order, you can still use a list making some optimizations.

    private val pairList = mutableListOf<Pair<Product, Int>>()
    
    fun addProduct(product: Product, quantity: Int) {
        pairList.forEachIndexed { index, (savedProduct, savedQuantity) ->
            if (savedProduct.productName == product.productName) {
                // This is the product we are searching for.
                pairList[index] = product to quantity + savedQuantity
                // We found the product and replaced it, we don't need to search for it anymore.
                return
            }
        }
        // We didn't find a product, add it as the last item.
        pairList += product to quantity
    }