Kotlin equals and hash code generator

kotlin hashcode example
kotlin hashcode implementation
kotlin hash function
kotlin data class hashcode override
kotlin default equals implementation
kotlin recursive equals call
kotlin data class deep equals
kotlin override equals operator

I am aware that in Kotlin classes will have an equals and hashcode created automatically as follows:

data class CSVColumn(private val index: Int, val value: String) {
}

My question is, is there a way to have the implementation just use one of these properties (such as index) without writing the code yourself. What was otherwise a very succinct class now looks like this:

data class CSVColumn(private val index: Int, val value: String) {

    override fun equals(other: Any?): Boolean {
        if (this === other) {
            return true
        }
        if (javaClass != other?.javaClass) {
            return false
        }
        other as CSVColumn
        if (index != other.index) {
            return false
        }
        return true
    }

    override fun hashCode(): Int {
        return index
    }

}

In Java with Lombok, I can do something like:

@Value
@EqualsAndHasCode(of="index")
public class CsvColumn {
    private final int index;
    private final String value;
}

Would be cool if there were a way to tell Kotlin something similar.

From the Data Classes documentation you get:

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

So you have to implement equals() and hashCode() manually or with the help of a Kotlin Compiler Plugin.

hashCode, If two objects are equal according to the equals() method, then calling the hashCode method on each of the two objects must produce the same integer result. Android Studio -> Code -> Generate -> equals() and hashCode(). References: https://www.jetbrains.com/help/idea/generating-code.html#generate-equals-hashcode

You can't do something like this for data classes, they always generate equals and hashCode the same way, there's no way to provide them such hints or options.

However, they only include properties that are in the primary constructor, so you could do this for them to only include index:

data class CSVColumn(private val index: Int, value: String) {
    val value: String = value
}

... except you can't have parameters in the primary constructor that aren't properties when you're using data classes.

So you'd have to somehow introduce a secondary constructor that takes two parameters, like this:

class CSVColumn private constructor(private val index: Int) {

    var value: String = ""

    constructor(index: Int, value: String) : this(index) {
        this.value = value
    }

}

... but now your value property has to be a var for the secondary constructor to be able to set its value.

All this to say that it's probably not worth trying to work around it. If you need an non-default implementation for equals and hashCode, data classes can't help you, and you'll need to implement and maintain them manually.


Edit: as @tynn pointed out, a private setter could be a solution so that your value isn't mutable from outside the class:

class CSVColumn private constructor(private val index: Int) {

    var value: String = ""
        private set

    constructor(index: Int, value: String) : this(index) {
        this.value = value
    }

}

How does Kotlin implement equals and hashCode?, Hi, I just want to understand little more on how equals() and hashCode() are generated by Kotlin. Does Kotline default "class Foo" generates  Returns a hash code value for the object. The general contract of hashCode is: Whenever it is invoked on the same object more than once, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. If two objects are equal according to the equals()

I wrote a little utility called "stem", which allows you to select which properties to consider for equality and hashing. The resulting code is as small as it can get with manual equals()/hashCode() implementation:

class CSVColumn(private val index: Int, val value: String)  {
    private val stem = Stem(this, { index })

    override fun equals(other: Any?) = stem.eq(other)
    override fun hashCode() = stem.hc()
}

You can see its implementation here.

Ignoring certain properties when generating equals(), hashCode(), etc, Ignoring certain properties when generating equals(), hashCode(), etc If I understand correctly, Kotlin will generate equals() and hashCode() using If you need non-standard generation of any data class methods, you can  Use getters during code generation. If this checkbox is selected, the getters are used in equals() instead of direct fields access: getField() vs field. Click Next to open the next page. Page 2. Choose fields to be included in equals() Select the fields that should be used to determine equality.

I guess that we have to write equals()/hashCode() manually for now. https://discuss.kotlinlang.org/t/automatically-generate-equals-hashcode-methods/3779

It is not supported and is planning to be, IMHO.

Effective Kotlin: Item 11, With Kotlin's data class implementation, there is now often little need to write your implementing equals , the main premise is to calculate the hashCode based off Kotlin's data types of Int , Long , etc. provide hashCode functions, and it may  In Effective Java by Joshua Bloch, there are lots of details about how to write a hashCode function. With Kotlin’s data class implementation, there is now often little need to write your own as

I guess that we have to write equals()/hashCode() manually for now. https://discuss.kotlinlang.org/t/automatically-generate-equals-hashcode-methods/3779

It is not supported and is planning to be, IMHO.

Below are some reference which may be helpful.

https://discuss.kotlinlang.org/t/how-does-kotlin-implement-equals-and-hashcode/940 https://kotlinlang.org/docs/reference/data-classes.html https://medium.com/@appmattus/effective-kotlin-item-11-always-override-hashcode-when-you-override-equals-608a090aeaed

Generate equals() and hashCode() wizard, hashCode() or Alt+Insert. Use this wizard to generate equals() and hashCode() methods. Use getters during code generation. If this checkbox is selected,  Select Generate Equals(object) or Generate Equals and GetHashCode from the drop-down menu. In the Pick members dialog box, select the members you want to generate the methods for: Tip. You can also choose to generate operators from this dialog by using the checkbox near the bottom of the dialog.

Guide to hashCode() in Java, Simply put, hashCode() returns an integer value, generated by a hashing algorithm. Objects that are equal (according to their equals()) must  Configure one static instance of Equals and HashCode or EqualsAndHashCode and reuse it across all instances to minimize garbage. Use Java 8 lambdas to define which attributes should be compared and hashed. Easily honour the contracts between equals() and hashCode() without a lot of boilerplate code. No dependencies to other libraries; Examples

Generate equals() and hashCode() with Eclipse, We'll illustrate how powerful and convenient the Eclipse's code auto-generation is, and also emphasize that diligent testing of code is still  We use the Eclipse IDE to generate equals() and hashCode() using ‘Source->Generate hashCode() and equals()‘. Eclipse provides a dialog box like this: We can ensure all member variables are included by choosing ‘Select All'. Note that the options listed beneath Insertion Point: affect the style of the generated code.

Working With hashcode() and equals(), hashcode(): a method provided by java.lang. The Contract Between equals() and hashcode() Create a CRUD App With React, Kotlin, and Spring Boot How to Create Project-Specific Code Generators for Enterprise  A nice feature of Eclipse is that you can easily generate hashCode and equals methods for your Java class using the editor. You'll really appreciate this capability when you need to create these methods whenever you're doing anything related to sorting, comparisons, comparators, etc.

Comments
  • @Enzokie good point, but does adding that change the question at all?
  • It will just make first statement accurate ;)
  • Thanks for pointing this out. I corrected the example code.
  • You can write that 'equals' function much more succinctly if you just treat it as a boolean expression instead of trying to bail out early: override fun equals(other: Any?) = this === other || (other is CsvColumn && index==other.index)
  • You can shorthand override fun hashCode() = listOf(each, specific, property).hashCode() * 31 and then override fun equals(other: Any?) = if (other is Type) hashCode() == other.hashCode() else false. It's not generating, but only a couple of lines to write then.
  • You can make value a val if you use the lazyinit attribute.