- source: Baeldung
- to compile: mvn package
- to run: mvn -q exec:java
public class Money {
private final int amount;
private final String currencyCode;
}
- Generate constructor
public Money(int amount, String currencyCode) {
this.amount = amount;
this.currencyCode = currencyCode;
}
- Generate Equals and hashcode
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Money money)) return false;
return amount == money.amount && Objects.equals(currencyCode, money.currencyCode);
}
@Override
public int hashCode() {
return Objects.hash(amount, currencyCode);
}
In Main::main
:
Money expense = new Money(55, "CAD");
Money income = new Money(55, "CAD");
System.out.println("expense == expense? " + expense.equals(expense));
System.out.println("expense == income? " + expense.equals(income));
public class VoucherInherit extends Money {
private final String company;
public VoucherInherit(int amount, String currencyCode, String company) {
super(amount, currencyCode);
this.company = company;
}
}
- Generate equals/hashcode automatically:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
VoucherInherit that = (VoucherInherit) o;
return Objects.equals(company, that.company);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), company);
}
In Main::main
:
Money cash = new Money(42, "CAD");
Money voucherI = new VoucherInherit(42, "CAD", "AirCanada");
System.out.println("voucher == cash? " + voucherI.equals(cash));
System.out.println("cash == voucher? " + cash.equals(voucherI));
Execution result (We just broke the equals relation!):
voucher == cash? false
cash == voucher? true
Create a Voucher class:
public class Voucher {
private final String store;
private final Money money;
public Voucher(String store, Money money) {
this.store = store;
this.money = money;
}
public Money value() {
return this.money;
}
}
Voucher voucher = new Voucher("AirCanada", new Money(42, "CAD"));
System.out.println("voucher == cash? " + voucher.equals(cash));
System.out.println("cash == voucher? " + cash.equals(voucher));
System.out.println("cash == voucher.value()? " + cash.equals(voucher.value()));
System.out.println("voucher.value() == cash? " + voucher.value().equals(cash));
Now it is ok from a semantic point of view. A voucher is not a money, but its value is.
public class Team {
private final String city;
private final String sport;
}
- Generate constructor
public Team(String city, String sport) {
this.city = city;
this.sport = sport;
}
- Generate Equals
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Team team = (Team) o;
return Objects.equals(city, team.city) && Objects.equals(sport, team.sport);
}
Map<Team, String> nhl = new HashMap<>();
nhl.put( new Team("Toronto", "hockey"), "Maple leafs");
nhl.put( new Team("Ottawa", "hockey"), "senators");
nhl.put( new Team("Montreal", "hockey"), "canadiens");
Team leafs = new Team("Toronto", "hockey");
System.out.println("Toronto's hockey team? " + nhl.getOrDefault(leafs, "unknown"));
System.out.println("Leaf as a key? " + nhl.keySet().contains(leafs));
System.out.println("Leaf as an element? " + nhl.keySet().stream().toList().contains(leafs));
System.out.println("----------------");
So the (Toronto, Hockey) is present in the list of keys, but "contains" returns false... Because lists relies on equality, but Hash* structures on hashcodes!
public class TeamBoth {
private final String city;
private final String sport;
}
- Generate constructor
public TeamBoth(String city, String sport) {
this.city = city;
this.sport = sport;
}
- Generate both equals and hashcode
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TeamBoth teamBoth = (TeamBoth) o;
return Objects.equals(city, teamBoth.city) && Objects.equals(sport, teamBoth.sport);
}
@Override
public int hashCode() {
return Objects.hash(city, sport);
}
Map<TeamBoth, String> nhlBis = new HashMap<>();
TeamBoth leafBis = new TeamBoth("Toronto", "hockey");
nhlBis.put(new TeamBoth("Toronto", "hockey"), "Maple leafs");
nhlBis.put(new TeamBoth("Ottawa", "hockey"), "senators");
nhlBis.put(new TeamBoth("Montreal", "hockey"), "canadiens");
System.out.println("Toronto's hockey team? " + nhlBis.getOrDefault(leafBis, "unknown"));
System.out.println("Leaf as a key? " + nhlBis.keySet().contains(leafBis));
System.out.println("Leaf as an element? " + nhlBis.keySet().stream().toList().contains(leafBis));