APC Apps
APC Apps

Reputation: 31

how to remove the repeated item in arraylist of class

I'm trying to data from my server put them in my app, using RecyclerView and volley, now because of that I'm using an adapter and this is my adapter class

class TypeAdapter(var con: Context, var list: ArrayList<TypeItems>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onBindViewHolder(p0: RecyclerView.ViewHolder, p1: Int) {

    (p0 as ItemView).bind(list[p1].cartype, list[p1].typetype, list[p1].modeltype, list[p1].photype)

}
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): RecyclerView.ViewHolder {
    val v= LayoutInflater.from(con).inflate(R.layout.car_model_item, p0, false)

    return ItemView(v)
}

override fun getItemCount(): Int {
    return list.size
}

class ItemView(itemVeiw: View) : RecyclerView.ViewHolder(itemVeiw) {

    fun bind(car_type: String, type: String, modele: String, ph: String) {

        Picasso.with(itemView.context).load(ph).into(itemView.type)

        itemView.name.text= "$car_type $type"
        itemView.model.text= modele


    }
}
}

and this is my TypeItems class

class TypeItems(car_typetype: String, typetype: String, modeletype: String, phtype: String) {
var cartype:String = car_typetype
var typetype:String = typetype
var modeltype:String = modeletype
var photype:String = phtype

}

and this is my main class

class CarModelActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_car_model)

    val list= ArrayList<TypeItems>()

    val rq= Volley.newRequestQueue(this)

    val  url= ("http://test123456789.cf/sell_items/reportall.php?car_type=${car_item.cartype}").replace(" ", "%20")

    val srr= StringRequest(Request.Method.GET, url ,
        Response.Listener { response ->

            //converting the string to json array object
            val array = JSONArray(response)

            list.clear()

            //traversing through all the object
            for (i in 0 until array.length()) {

                //getting item object from json array
                val product = array.getJSONObject(i)


                //ex Image
                var url2= "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRj3LA1ERJCx8lM-qHsgaW_5IgzeW21w-Ona7iI05E9aoXrImtl"

                //adding the product to item list
                list.add(
                    TypeItems(
                        product.getString("car_type"),
                        product.getString("type"),
                        product.getString("model"),
                        url2
                    )
                )

            }

            //creating adapter object and setting it to recyclerview
            val adapter = TypeAdapter(this.applicationContext, list)
            rv.layoutManager= GridLayoutManager(this, 2)
            rv.adapter = adapter

        }, Response.ErrorListener { error ->
            Toast.makeText(this, error.message, Toast.LENGTH_LONG).show()
        })

    rq.add(srr)

}
}

this is image of the result

now I want to remove the repeated items from my list, I want to sort by car_type and type and model, if the item is repeated, I want to remove it

Upvotes: 1

Views: 652

Answers (3)

user2340612
user2340612

Reputation: 10704

Please note that the accepted answer suggests using list.contains(x) before possibly adding the element to the list. However, contains takes O(n) and you're doing that check for each item you get in response, so you'll have a total complexity of O(n^2). Performance could be quite bad if you have many items, and this means your application could be unresponsive and UX could be affected. Moreover, items are ordered in insertion order, so we need to explicitly sort it in the desired order – adding at least another O(n*log(n)), which is though dominated by the previous O(n^2).

A TreeSet could hence be a better fit for this particular use case – as suggested by @Rogue and @taha – since it automatically prevents duplicates, it has a complexity of O(log(n)) in insertion and it enforces some kind of sorting.

Here's an example of how to use it:

data class TypeItems(
    val car: String,
    val type: String,
    val model: String,
    val ph: String
)

fun main() {
    // simulates a response from the server
    val response = listOf(
        TypeItems("carBBB", "typeBBB", "modelBBB", "phBBB"),
        TypeItems("carAAA", "typeAAA", "modelAAA", "phAAA"),
        TypeItems("carAAA", "typeAAA", "modelAAA", "phAAA"),
        TypeItems("carCCC", "typeZZZ", "modelYYY", "phCCC"),
        TypeItems("carCCC", "typeXXX", "modelWWW", "phCCC"),
        TypeItems("carCCC", "typeXXX", "modelVVV", "phCCC")
    )

    // creates an empty TreeSet with the desired sorting
    val set = TreeSet<TypeItems>(
        Comparator.comparing(TypeItems::car)
            .thenComparing(TypeItems::type)
            .thenComparing(TypeItems::model)
            .thenComparing(TypeItems::ph) // needed for "consistency with equals"
    )

    // add each element to the set, it'll handle duplicates
    response.forEach { set.add(it) }

    // do something with the resulting set: print each item on a new line
    set.forEach {
        println(it)
    }
}

That'll print:

TypeItems(car=carAAA, type=typeAAA, model=modelAAA, ph=phAAA) // duplicate removed
TypeItems(car=carBBB, type=typeBBB, model=modelBBB, ph=phBBB) // car order enforced (as B > A)
TypeItems(car=carCCC, type=typeXXX, model=modelVVV, ph=phCCC) // type order enforced (as X > B)
TypeItems(car=carCCC, type=typeXXX, model=modelWWW, ph=phCCC) // model order enforced (as W > V)
TypeItems(car=carCCC, type=typeZZZ, model=modelYYY, ph=phCCC)

Upvotes: 0

samaromku
samaromku

Reputation: 559

You should use the data class. It will contain overriding equals() method inside:

data class TypeItems(
    val car_typetype: String,
    val typetype: String,
    val modeletype: String,
    val phtype: String
)

After digging into this issue, I found, that you cannot call method get() on the Set collection. So, this code won't work: (p0 as ItemView).bind(list[p1].cartype, list[p1].typetype, list[p1].modeltype, list[p1].photype)
Summarize, Set won't help you. To solve your issue, you need just to invoke defensive check:

val typeItems = TypeItems(
                product.getString("car_type"),
                product.getString("type"),
                product.getString("model"),
                url2
        )
        if(!list.contains(typeItems)) {
            list.add(typeItems)
        }

Therefore, there is another way, to solve this issue: instead of
val adapter = TypeAdapter(this.applicationContext, list)
invoke
val adapter = TypeAdapter(this.applicationContext, list.distinct())
Method distinct() return you unique values of your list in the same order. Don't forget to make it data class though.

Upvotes: 2

taha
taha

Reputation: 771

replace val list= ArrayList<TypeItems>() with val set = SortedSet<TypeItems>()

and override equals method of TypeItems:

override fun equals(other: Any?): Boolean {
    if (other is TypeItems) {
        other.cartype == this.cartype && ... // replace TypeItems fields
    } else {
        false
    }
}

also if you want to be sorted , TypeItems has to implement Comparable https://docs.oracle.com/javase/8/docs/api/java/util/SortedSet.html

Upvotes: 0

Related Questions