首页 > 解决方案 > 条件说列表's 不是 .equal(),即使它们是相同的

问题描述

新列表来自 SQLite 数据库。

oldList,通过android提供的@Embedded接口存储JOINED表的第一行和第二行。

填充它的查询应该只获取那 2 行,因为它们符合特定的 WHERE 子句。

在右表中执行事务时,例如插入外键尚未“指向”(?)的第 3 行指向左表,并且前 2 行(连接行)没有更改,观察者得到调用,并给了我相同的 2 行,但 java 代码告诉我它们是不同的。

可以理解,观察者给我的响应好像数据发生了变化,因为连接表确实整体发生了变化,并且 SQL 查询需要检查插入的第三行是否符合施加的条件(它确实不是),但不清楚的是为什么 java 代码获取相同的 2 行,并告诉我它们与刚才存储的相同 2 行不同。

起初我认为这与列表是 .get() 来自 HashMap<K,V> 的事实有关,也可能是这样。

        @Override
        protected void onFound(List<X> xes, int liveDataId) {


            List<X> xOldList = listHashMap.get(liveDataId);


            if (xOldList == null) {
                Log.d(TAG, "onFound: list not found on HasMap adding response");

                listHashMap.put(liveDataId, xes);

                if (listHashMap.size() == sources.size()) {
                    Log.d(TAG, "onFound: HashMap complete, converting HasMap");
                    ends(listHashMap);
                }

            } else {
                if (!xOldList.equals(xes)) {
                    Log.d(TAG, "onFound: oldList not the same as new one!");
                    if (xes.size() > 0) {
                        Log.d(TAG, "onFound: new list size greater than 0");
                        synchronizedSubmitList(xes, xOldList, liveDataId);
                    } else {
                        Log.d(TAG, "onFound: newList size is zero");
                        listHashMap.put(liveDataId, xes);
                        ends(listHashMap);
                    }
                }
            }
        }

日志

在此处输入图像描述

@Embedded Pojo

公共类 PieceQuantityAndPiece 实现 EntityInterface { private static final String TAG = "PieceQuantityAndPiece";

@Embedded
public PieceQuantity pieceQuantity;

@Relation(
        parentColumn = "child_piece_id",
        entityColumn = "piece_id"
)
public Piece piece;


public PieceQuantityAndPiece() {
}

}

对左表施加的查询

@Transaction
@Query("SELECT * FROM piece_quantity_table WHERE folder_id = :folderId")
LiveData<List<PieceQuantityAndPiece>> getPieceQuantityAndPiecesAtFolder(int folderId);

在触发 onChanged() 的右表上执行的事务:

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Piece piece);

@Query("UPDATE piece_table SET _total = :total, _date_of_last_edit = :lastEdited WHERE piece_id = :pieceId")
void updatePieceTotalAt(int total, long lastEdited, int pieceId);

标签: javalistsqliteequals

解决方案


我设法通过迭代它们的单独元素来比较两个列表的相等性,然后,通过使用我在类中闲逛的 2 个功能接口,如果它们的 Id 相同,则返回一个布尔值,如果一个字段另一份的兴趣(内容)也相同;我分别比较了这两个项目。

这里的一线希望是,关于迭代这么多的优化程度,旧列表和新列表之间的大小差异最多一次始终为 1 项,但如果考虑到我会提出的情况删除更多项目的选项,一切仍然在后台发生,而且我相信,还有足够的条款需要满足,以确保做绝对必要的事情。

项目的顺序并不是真正的问题,因为它们总是会以相同的顺序被获取,如果它们是无序的,列表仍然会直接进入一个列表区分器类,该类可以干净地管理它们。此外,如果内容的顺序不同,则有 100% 的可能性是因为无论如何某些东西确实发生了变化。

至于调试,他们的日志似乎更有帮助,可能是因为我对调试的经验不够。

日志显示,每个字段中的项目确实相同,但它们的哈希码不同,这很明显,LiveData 没有内存,只是 set() 和 fin。

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

即使没有声明该 T 值,new它仍然“指向”其原始来源吗?我怀疑它的来源是 SQLite。

即使通过将每个元素独立地类型转换为它们各自的子类型,它们仍然不同。

但是深入 List.equal(List) 方法,我发现我的对象永远不会相等,因为:

public boolean equals(Object obj) {
    return (this == obj);
}

所以那是一个== ...并且他们总是有不同的哈希码...

这就是我开始一一比较它们的领域(它们是相同的),以及它们的原语最终可比较的地方。

拥有所有 SQLite 实体的超类型接口,我可以比较它们的 id 和它们最重要的字段(在本例中为 last_date_edited),并使用前面提到的 2 个函数接口,我做了一个子句条件:

private boolean verifyEquality(
        List<X> oldList, List<X> newList,
        @NonNull ListDifferentiator4.AreIdsTheSame<X> areIdsTheSame,
        @NonNull ListDifferentiator4.AreContentsTheSame<X> areContentsTheSame
) {
    for (int i = 0; i < oldList.size(); i++) {

        X oldX = oldList.get(i);
        X newX = newList.get(i);

        if (!areIdsTheSame.areIdsTheSame(newX, oldX) || !areContentsTheSame.areContentsTheSame(newX, oldX)) {
            Log.d(TAG, "verifyEquality: items are different");
            return false;
        }
    }
    Log.d(TAG, "verifyEquality: Lists are the same");
    return true;
}

onFound 方法()...

        @Override
        protected void onFound(List<X> xes, int liveDataId) {


            List<X> xOldList = listHashMap.get(liveDataId);


            if (xOldList == null) {
                Log.d(TAG, "onFound: list not found on HasMap adding response");
                listHashMap.put(liveDataId, xes);

                if (listHashMap.size() == sources.size()) {

                    Log.d(TAG, "onFound: HashMap complete, converting HasMap");
                    convertAndSet(listHashMap);
                }

            } else {
                Log.d(TAG, "onFound: livedataId is: " + liveDataId);

                if (xOldList.size() == xes.size()) {
                    Log.d(TAG, "onFound: Lists are the same size!");

                    if (xOldList.size() != 0) {
                        Log.d(TAG, "onFound: sizes are not 0");
                        boolean areEqual = verifyEquality(
                                xOldList,
                                xes,
                                areIdsTheSame,
                                areContentsTheSame
                        );
                        Log.println(Log.ASSERT, TAG, "onFound: are equal boolean 1st is: " + areEqual);
                        Log.d(TAG, "onFound: list size is: " + xes.size());

                        if (!areEqual) {
                            Log.println(Log.ASSERT, TAG, "onFound: oldList not the same as new one!");
                            listHashMap.put(liveDataId, xes);
                            convertAndSet(listHashMap);

                        } else {
                            Log.println(Log.ASSERT, TAG, "onFound: LISTS WHERE THE SAME!");
                        }
                    }


                } else {

                    Log.println(Log.ASSERT, TAG, "onFound: Lists are not the same size");

                    if (xes.size() > 0) {

                        Log.d(TAG, "onFound: new list size greater than 0");
                        synchronizedSubmitList(xes, xOldList, liveDataId);

                    } else {

                        Log.d(TAG, "onFound: newList size is zero");
                        listHashMap.put(liveDataId, xes);
                        convertAndSet(listHashMap);
                    }

                }
            }
        }

使用列表微分器接口初始化的整个类...

    liveDataListSource = new SourceMergingLiveData<>(
            (newX, oldX) -> newX.getPrimaryKey() == oldX.getPrimaryKey(),
            (newX, oldX) -> newX.getFieldElement().equals(oldX.getFieldElement())
    );

日志...

在此处输入图像描述

作为最后的想法,这被证明是一个实例,其中 2 个完全相等的对象每次都有不同的哈希码,这与这个答案所说的相反。

https://stackoverflow.com/a/5443140/11214643


推荐阅读