簡體   English   中英

我將如何遞歸比較兩個相同但未知類型的 Java 對象的字段值?

[英]How would I compare field values of two Java objects of the same but unknown type recursively?

我們正在使用 JAXB 將 XML 配置文件解析為 Java 對象。 XML 文件是版本化的,在將 1.0 和 2.0 版加載到對象中后,我們希望遞歸比較兩個相同但未知類型的對象(各種事物有許多不同的配置)及其字段值並打印出差異.

一個對象可能如下所示。

@XmlRootElement(name = "HelloWorld")
public class HelloWorldConfiguration {
    private List<HelloWorldObject> helloWorldObjects = new ArrayList<HelloWorldObject>();

    public HelloWorldConfiguration() {
        HelloWorldObject o = new HelloWorldObject();
        helloWorldObjects.add(o);
        helloWorldObjects.add(o);
        helloWorldObjects.add(o);
        helloWorldObjects.add(o);
        helloWorldObjects.add(o);
    }

    @XmlElement(name = "helloWorldObject")
    public List<HelloWorldObject> getHelloWorldObjects() {
        return helloWorldObjects;
    }

    public void setHelloWorldObjects(List<HelloWorldObject> helloWorldObjects) {
        this.helloWorldObjects = helloWorldObjects;
    }
}

public class HelloWorldObject {
    private Stage firstName = new Stage("Tony");
    private Stage secondName = new Stage("Stark");
    
    public Stage getFirstName() {
        return firstName;
    }

    public void setFirstName(Stage firstName) {
        this.firstName = firstName;
    }

    public Stage getSecondName() {
        return secondName;
    }

    public void setSecondName(Stage secondName) {
        this.secondName = secondName;
    }

}

例如,我們想知道有關上述 HelloWorldConfiguration 對象的以下更改?

  • 列表中有額外的“HelloWorldObject”項目(必須在屏幕上打印具有其屬性的項目)
  • 位置 n 處的“HelloWorldObject”具有新的“firstName”值(更改的字段或 XML 元素的名稱及其值應打印)
  • 新的“HelloWorldObject”列表縮短了 2 個以下元素(缺少的元素必須與所有屬性和值一起打印)

我的問題如下。

  • 您是通過 Java 對象級別的反射來解決這個問題還是比較兩個不同的 XML 文件?
  • 是否有任何圖書館已經為我做這樣的事情? 在 XML 或 Java 對象級別?
  • 有什么例子嗎?

免責聲明。 我是JAXB2 Basics插件包的作者,其中包括JAXB2 Equals 插件


如果您從 XML 模式生成您的類,那么JAXB2 Equals 插件在此用例中可能對您有用。

JAXB2 Equals 插件能夠生成對 JAXB 類實例進行深度結構遍歷值比較的equals方法:

public boolean equals(Object object) {
    final EqualsStrategy strategy = JAXBEqualsStrategy.INSTANCE;
    return equals(null, null, object, strategy);
}

public boolean equals(ObjectLocator thisLocator, ObjectLocator thatLocator, Object object, EqualsStrategy strategy) {
    if (!(object instanceof PurchaseOrderType)) {
        return false;
    }
    if (this == object) {
        return true;
    }
    final PurchaseOrderType that = ((PurchaseOrderType) object);
    {
        USAddress lhsShipTo;
        lhsShipTo = this.getShipTo();
        USAddress rhsShipTo;
        rhsShipTo = that.getShipTo();
        if (!strategy.equals(LocatorUtils.property(thisLocator, "shipTo", lhsShipTo), LocatorUtils.property(thatLocator, "shipTo", rhsShipTo), lhsShipTo, rhsShipTo)) {
            return false;
        }
    }
    {
        USAddress lhsBillTo;
        lhsBillTo = this.getBillTo();
        USAddress rhsBillTo;
        rhsBillTo = that.getBillTo();
        if (!strategy.equals(LocatorUtils.property(thisLocator, "billTo", lhsBillTo), LocatorUtils.property(thatLocator, "billTo", rhsBillTo), lhsBillTo, rhsBillTo)) {
            return false;
        }
    }
    // ...
    return true;
}

我希望你有這個想法。 您可以提供一個“定位器”來跟蹤被比較的事物的位置,以及一個對各個值進行比較的策略。

結果,您可以:

  • 對模式派生的 JAXB 類實例進行深入比較。
  • 知道什么是不同的(確切的值)。
  • 知道差異在哪里(對象結構中的確切位置)。

整個過程是無反射的,因此速度非常快。

下面是另一個項目的片段。 這是來自我比較對象“之前”和“之后”並記錄差異的測試之一。

    final EqualsStrategy strategy = new org.jvnet.hyperjaxb3.lang.builder.ExtendedJAXBEqualsStrategy() {

        @Override
        public boolean equals(ObjectLocator leftLocator,
                ObjectLocator rightLocator, Object lhs, Object rhs) {
            if (!super.equals(leftLocator, rightLocator, lhs, rhs)) {
                logger.debug("Objects are not equal.");
                super.equals(leftLocator, rightLocator, lhs, rhs);
                logger.debug("Left: "
                        + (lhs == null ? "null" : lhs.toString()));
                if (leftLocator != null) {
                    logger.debug("At [" + leftLocator.getPathAsString()
                            + "].");
                }
                logger.debug("Right: "
                        + (rhs == null ? "null" : rhs.toString()));
                if (rightLocator != null) {
                    logger.debug("At [" + rightLocator.getPathAsString()
                            + "].");
                }
                return false;
            } else

            {
                return true;
            }
        }

    };

另一方面,這種方法並不是真正的“差異”,因為您可能從 VCS 知道它。 它只是說有些不同,但不計算任何“最短編輯距離”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM