Set of object contains by object with value (not reference) (java 7) - java

I have my object with some feilds.
public class MyObject{
private String a;
private String b;
}
I have a Set contains objects like this :
Set<MyObject> thirdSet = new HashSet<MyObject>();
Set<MyObject> firstSet=getFirstSet();
Set<MyObject> secondSet = getSecondeSet();
for (MyObjectobj : firstSet) {
if (!secondSet.contains(obj)) {
thirdSet.add(obj);
}
}
I need to select all obj that not contains in my secondSet into thridSet (obj with value not by reference)
Is it possible or using collection is more better?

You'll need to override both equals and hashcode methods in your object. I'd recommend using the java 7 Objects utility methods if you can to prevent NullPointerExceptions.
#Override
public boolean equals(Object other) {
if (!(other instanceof MyObject)) {
return false;
}
MyObject that = (MyObject) other;
return Objects.equals(a, that.a) && Objects.equals(b, that.b);
}
#Override
public int hashcode() {
Objects.hash(a, b);
}
I'd also recommend taking a look at the third party library Guava if possible which would simplify your code.
Set<MyObject> thirdSet = new HashSet<>(Sets.difference(firstSet, secondSet));
Note wrapping it in a new HashSet so it can be modified (if you don't need to modify it you can remove that)

You should override Object#equals and Object#hashCode in MyObject.java.
#Override
public boolean equals(Object o) {
if (!(o instanceof MyObject)) {
return false;
}
MyObject m = (MyObject) o;
return a.equals(m.a) && b.equals(m.b);
}
#Override
public int hashCode() {
return Objects.hash(a, b);
}
Also if you're allowed to use external libraries, you should check out Guava's Sets#difference.

Related

HashMap get comes back with null even tho key is in it

I'm trying to create a swing chessboard with icons and i have trouble with putting the icons onto the JButtons using a HashMap.
Here are the classes that i'm working with:
Main Class
public class GameGUI extends JFrame {
private JButton tiles[][] = new JButton[8][8];
private HashMap<PieceKey, ImageIcon> icons = new HashMap<>();
public GameGUI(){
//swing shenannigans
initImages();
Tile[][] fenTiles = game.getFen().getTiles();
for(int row = 0; row <= 7; row++){
for(int column = 0; column <= 7; column++){
Piece piece = fenTiles[row][column].getPiece();
if(piece != null) {
tiles[row][column].setIcon(icons.get(new PieceKey(piece.getType(), piece.getColor())));
}
}
}
}
public void initImages(){
icons.put(new PieceKey(PieceType.pawn, Team.white), new ImageIcon("pieces/wpawn.png"));
//.....
}
public static void main(String args[]){
GameGUI asd = new GameGUI();
}
}
PieceKey class
public class PieceKey {
PieceType type; //enum
Team color; //enum
public PieceKey(PieceType type, Team color) {
this.color = color;
this.type = type;
}
#Override
public boolean equals(Object o){
if(this == o)
return true;
if(!(o instanceof PieceType))
return false;
PieceKey key = (PieceKey) o;
return this.type == key.type && this.color == key.color;
}
#Override
public int hashCode(){
return type.toString().hashCode() * color.toString().length();
}
}
Team enum
public enum Team {
white, black;
}
PieceType enum
public enum PieceType {
pawn, rook, knight, bishop, king, queen;
}
My problem is that whenever i call
icons.get(new PieceKey(piece.getType(), piece.getColor()));
It return null, so i cant put the icons onto the buttons, it works fine if i do it manually so the problem is with the HashMap. I tried to override the equals and the hashcode function in the PieceKey class but it doesn't seem to work.
The problem may be in your PieceKey equals method. You are using incorrectly PieceType while using instanceof:
#Override
public boolean equals(Object o){
if(this == o)
return true;
// Please, note this, it will always return false, and the `Map`
// `equals` method for `get` and `put` will not work
if(!(o instanceof PieceType))
return false;
PieceKey key = (PieceKey) o;
return this.type == key.type && this.color == key.color;
}
If should be:
#Override
public boolean equals(Object o){
if(this == o)
return true;
// Please, note this
if(!(o instanceof PieceKey))
return false;
PieceKey key = (PieceKey) o;
return this.type == key.type && this.color == key.color;
}
The Answer by jccampanero seems correct about you having a problem with the implementation details of your override of Object :: equals.
Record
Another solution is to avoid even needing to write your own equals and hashCode. If your PieceKey class is meant primarily to transparently and immutable carry data, define the class as a record.
Your entire class reduces to this simple short line.
public record PieceKey ( PieceType type , Team color ) {}
As a record, the compiler implicitly creates the constructor, getters, equals & hashCode, and toString.
You make an instance in the same way as with a conventional class.
new PieceKey( PieceType.pawn , Team.white )
Bonus tip: In Java 16 and later, as part of the work done to create the records feature, we can now declare records, enums, and interfaces locally.
You should use your IDE to generate your hashCode and equals implementation.
The most default implementation you should have should be something like:
#Override
public int hashCode() {
return Objects.hash(type, color); // java.util.Objects
}
#Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof PieceKey) return false;
PieceKey other = (PieceKey) o;
return Objects.equals(type, other.type)
&& Objects.equals(color, other.color);
}
Note that you don't need this at all with Java 17 records:
public record PriceKey(PieceType type, Team color) {}
hashCode() and equals() are by generated using type/color.
type and color are final by default.

Can equals() and hashCode() be lambdas?

I am new to Java. Can someone explain to me what is the difference between using lambda and method here?
Method equals()
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Book)) {
return false;
}
Book book = (Book) o;
if (!author.equals(book.author)) {
return false;
}
return title.equals(book.title);
}
Lambda equals()
public Function<Object, Boolean> equals = (Object o) -> {
if (this == o) {
return true;
}
if (!(o instanceof Book)) {
return false;
}
Book book = (Book) o;
if (!author.equals(book.author)) {
return false;
}
return title.equals(book.title);
};
Method hashCode()
#Override
public int hashCode() {
return 31 * author.hashCode() + title.hashCode();
}
Lamba hashCode()
public Supplier<Integer> hashCode = () -> 31 * author.hashCode() + title.hashCode();
I wanted to use Lambda instead of method for equals and hashCode.
Is it OK?
No, it is not OK. Java defines the methods boolean equals(Object) and int hashCode(). This is a specific signature and your suggested solution doesn't meet that signature and doesn't override the default implementation from Object (in fact, they are not even methods).
You could use a lambda in your equals and hashCode, but that would just add a needless level of indirection, and make your code harder to read.

Is there any build in Java way to make a Set out of a combination of 2 ints?

This is my code:
private class UniqueClassByTwoIntProperties {
private final int propertyOne;
private final int propertyTwo;
UniqueCase(final int propertyOne, final int propertyTwo) {
this.propertyOne= propertyOne;
this.propertyTwo= propertyTwo;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (!(obj instanceof UniqueCase)) {
return false;
}
UniqueClassByTwoIntProperties unique = (UniqueClassByTwoIntProperties) obj;
return unique.claimApplicationId == claimApplicationId && unique.claimCoverageId == claimCoverageId;
}
#Override
public int hashCode() {
return Objects.hash(propertyOne, propertyTwo);
}
}
I am looping through a list with objects, where I want to get the unique's in the following way:
myList.stream()
.map(row -> new UniqueClassByTwoIntProperties(row.getOne(), row.getTwo()))
.collect(Collectors.toSet());
I was wondering if there was a build-in class/method in Java. I have looked into dictionaries and MultiMapValues, but it was a bit hacky.
You can simply do it as:
Set<UniqueClassByTwoIntProperties> uniques = new HashSet<>(myList);
Aside: Make sure the hashCode and equals of the objects are implemented correctly for the object to be comparable.
If you just want the List of uniques then you can use Stream.distinct as :
List<UniqueClassByTwoIntProperties> uniques = myList.stream()
.distinct() // for unique objects
.collect(Collectors.toList());

Java: add element after an element in the LinkedList

I want to add an element after an element in the list if list already contain that element otherwise I want to add this new element to beginning
of the list.
Somehow below code is not working.
Any suggestions?
Does this approach correct performance wise?
public class HelloWorld
{
public static void main(String[] args) {
LinkedList<Task> l =new LinkedList<Task>();
l.add(new Task("a"));
l.add(new Task("b"));
l.add(new Task("c"));
int index;
if((index = l.lastIndexOf(new Task("a"))) != -1){
l.add(++index, new Task("5"));
}else{
l.addFirst(new Task("6"));
}
System.out.println(l);
}
}
class Task{
String value;
Task(String v){
value = v;
}
public boolean equals(Task t){
return t.value.equals(this.value);
}
public String toString(){
return this.value;
}
}
Output produces: [6,a,b,c]
Expected output: [a,5,b,c]
You are not overriding Object#equals in your Task class.
You need to parametrize it with Object, otherwise it's an overload.
That in turn doesn't allow your new Task("a") to be equal to new Task("a"), as Object.equals in invoked instead, and the references don't match.
This in turn will cripple your lastIndexOf invocation with unexpected results.
Example
#Override
public boolean equals(Object obj) {
// TODO your code, i.e. based on the "value" field
}
If you're using an IDE (which I recommend), you will have features allowing to draft equals (and hashCode) implementations based on your desired properties.
Your equals should look like that.
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Task task = (Task) o;
return value != null ? value.equals(task.value) : task.value == null;
}

Java ArrayList does not use overriden equals(Object o) method to compare

Why does ArrayList's contains(Object o) does not run my overridden equals(Object o) method? Consider this code:
private class TargetRC {
public RComponent rc;
public TargetRC(RComponent e) {
rc = e;
}
#Override
public boolean equals(Object o) {
if (o instanceof RComponent)
return o == rc;
else
return o == this;
}
}
private ArrayList<TargetRC> list = new ArrayList<TargetRC>();
public void add(RComponent e) {
list.add(new TargetRC(e));
System.out.println(list.contains(e));
}
As you see it is:
Symetric because o == rc when and only when rc == o
Reflexive because rc == rc
for any RComponent used in comparison.
Adding any element through visible here add method prints always false. No println works inside the equals method. Changing == operators to equals does not make any difference. What is wrong here?
You test
list.contains(e)
with e being a RComponent.
So the list calls RComponent.equals(Object) for every element in your list
which always returns false.
Ok, only thing I had to do was to override ArrayList's indexOf method like this:
private ArrayList<TargetRC> list = new ArrayList<TargetRC>(){
#Override
public int indexOf(Object o){
for(int i=0; i<size(); ++i){
if(get(i).equals(o)) return i;
}
return -1;
}
};

Categories