1

Trying to understand distinct() and distinctBy function to check duplicates. when i try "distinct" with list of strings, it works fine. when i try it with Type "Any" with custom class NO luck :( can anyone please help me understand?

    var a = ArrayList<Any>()
    val terry = Person("Terry",13)
    val joe = Person("Joe", 20)
    val sam1 = Person("Sam",33 )
    a.add(terry)
    a.add(joe)
    a.add(sam1)

    var b = ArrayList<Any>()
    val valdi = Person("Valdi",55)
    val tak = Person("Tak", 54)
    val sam2 = Person("Sam",33 )
    b.add(valdi)
    b.add(tak)
    b.add(sam2)

    a.addAll(b)

    val c = a.distinct() 
    println(c) //prints all 6 items. sam1 and sam2 is duplicated.
Terry
  • 107
  • 2
  • 11
  • I tried your code on [Kotlin Playground](https://play.kotlinlang.org/) and it does not duplicate `sam1` and `sam2` with `Person` being a `data class` – Saurabh Thorat Dec 26 '19 at 07:30

2 Answers2

4

The only issue I can think of is that your Person class is not a data class or it does not have the proper Primary constructor.

data class Person(
    val name: String,
    var age: Int
)

If your Person class is like that, then:

fun findDistinct() {
    val a = ArrayList<Any>()
    val terry = Person("Terry", 13)
    val joe = Person("Joe", 20)
    val sam1 = Person("Sam", 33)
    a.add(terry)
    a.add(joe)
    a.add(sam1)

    val b = ArrayList<Any>()
    val valdi = Person("Valdi", 55)
    val tak = Person("Tak", 54)
    val sam2 = Person("Sam", 33)
    b.add(valdi)
    b.add(tak)
    b.add(sam2)

    a.addAll(b)

    val c = a.distinct()
    println(c)
}

Will result in:

[Person(name=Terry, age=13), Person(name=Joe, age=20), Person(name=Sam, age=33), Person(name=Valdi, age=55), Person(name=Tak, age=54)]

Like you expected

BTW, having data class means that class automatically generates the equals(), hashCode(), toString(), copy() methods. Also - Note that the compiler only uses the properties defined inside the primary constructor for the automatically generated functions. To exclude a property from the generated implementations, declare it inside the class body.

Housefly
  • 4,324
  • 11
  • 43
  • 70
  • Hi, how about removing "Sam" from `val sam2` ? because `val sam1` has existing value for "Sam" ? – Aldan Dec 02 '20 at 09:18
3

String defines equals() and hashCode() properly so that objects with the same contents are considered equal. Your Person class should do so (either directly or by using data class) to make distinct() and distinctBy() work properly.

The default implementation of these methods in Any, just like Java's Object, treats each instance as different from any other.

herman
  • 11,740
  • 5
  • 47
  • 58
  • (Short but sweet :-)  OP should note that `Any` defines `equals()` and `hashCode()` methods which treat each object as different from every other, so that's what you get it you _don't_ override them. – gidds Dec 26 '19 at 23:07