Как сравнить, если класс имеет много значений в файле?

#java

Вопрос:

Я хочу сравнить объект A с объектом B класса Fruit.
Я хочу получить значение true, если значение файла объекта равно значению файла объекта B

Я знаю, что A == B сравнивает адрес. Поэтому мне нужно переопределить равенства для сравнения.
Но в моем классе есть много областей.

Я создаю код для сравнения

 @Setter
@Getter
public class Fruit {
    //if I have 100 Filed
    int filed1;

    int filed2;

    int filed3;

    int filed4;

    ....


    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Fruit) {
            Fruit target = (Fruit)obj;
            // I want to compare this object with targetFooResponse
            if(this.getFiled1() != target.getFiled1()) {
                return false;
            }
            if(this.getFiled2() != target.getFiled2()) {
                return false;
            }
            //I need to add if condition of 98 in the future

            return true;
        }else {
            return false;
        }
    }
}
 

Я думаю, что мой код очень неэффективен.Я хочу уменьшить, если условия
Есть ли хороший способ сравнить?

Комментарии:

1. Ваш код уродлив, потому что иметь класс со 100 полями — ужасная идея. Но если это то, что у вас есть, то это не худший способ сравнить их. Кроме того, это «поле», а не «подано».

2. единственная оптимизация, которую я мог бы сделать, — это связать условия с amp;amp; оператором: this.getFiled1() == target.getFiled1 amp;amp; this.getFiled2 == target.getFIled2() ...

3. Полностью согласен с Йоахимом Зауэром, вот почему у нас есть концепция массива … Если вы еще не подвергли себя воздействию массива, найдите его…

4. Arrays.stream(getClass().getFields()).map(f->{if(!f.getName().startsWith("filed")) return true;f.setAccessible(true);try {return f.get(this).equals(f.get(obj));} catch (IllegalAccessException e) {e.printStackTrace();}return false;}).allMatch(e -> e) вернет, равны ли все filedN поля для двух объектов, но это грязный способ сделать это

Ответ №1:

Как уже упоминали другие, иметь класс со 100 полями-плохая идея. Это нарушает многие хорошие инженерные принципы SW.

Тем не менее, допустим, у вас есть класс со многими полями ( может быть, он генерируется автоматически? )

Вот милая идея. Если вы можете сделать свой класс сериализуемым , и все поля для проверки сериализуемы, вы можете сбросить каждый объект в поток массива байтов и сравнить потоки.

 import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;

class A implements Serializable {
    int a;
    int b;
    int c;
}

public class Example {

    public static void main(String[] args) throws IOException {

        A a1 = new A();     a1.a = 1;       a1.b = 2;       a1.c = 3;
        A a2 = new A();     a2.a = 1;       a2.b = 2;       a2.c = 3;
        byte[] bytes1 = getBytes(a1);
        byte[] bytes2 = getBytes(a2);
        System.out.println(Arrays.equals(bytes1,bytes2));
    }


    private static byte[] getBytes(A a) throws IOException {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);) {            

            out.writeObject(a);
            out.flush();
            return bos.toByteArray();
        }
    }
}
 

Комментарии:

1. Мне было бы неудобно ссылаться на сериализацию в equals() реализации. Я не пробовал, но не удивлюсь, если сериализация и объект equals() в какой-то момент включат вызов, который может привести к бесконечной рекурсии.

2. @JoachimSauer Ну , в моем примере этого нет ( переопределение для класса A), но кто знает, может быть, в некоторых сценариях.

3. Это милая идея. Спасибо