从 geoQuery 向 recyclerView 添加独特的项目

Add unique items to recyclerView from geoQuery

我创建了一个应用程序来显示我附近用户的项目。

我使用 geoQuery 找到了我附近的人,如果他们在我附近,我会在数据库中搜索他们拥有的物品,然后用他们填充 RecyclerView

我使用:

List<DiscoverItems> items = new ArrayList<>();

GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(Lat, Lon), Radius);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String key, GeoLocation location) {

        String UserID = key;

        if (!UserID.equals(auth.getUid())) {
            db.collection("Users").document(UserID).collection("MyItems").get().addOnCompleteListener(task_count -> {
                if (task_count.isSuccessful()) {
                    for (DocumentSnapshot document_near : task_count.getResult()) {
                        items.add(new DiscoverItems(document_near.getString("ItemID")));
                    }

                }
            });
        }

        discoverItemAdapter = new DiscoverItemAdapter(items, listener);
        rv_NearMeItems.setAdapter(discoverItemAdapter);

    }

    @Override
    public void onKeyExited(String key) {

    }

    @Override
    public void onKeyMoved(String key, GeoLocation location) {

    }

    @Override
    public void onGeoQueryReady() {

    }

    @Override
    public void onGeoQueryError(DatabaseError error) {

    }
});

但是,我的问题是如果某些用户拥有相同的物品,因为它会在 recyclerView 中出现两次,而我希望它具有独特的物品。

是否有任何解决方案可以让我先检查我的项目列表是否重复,然后再添加它们?

我尝试执行以下操作:

List<DiscoverItems> items= new ArrayList<>();
Set<DiscoverItems> itemkset = new HashSet<>();

GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(Lat, Lon), Radius);
geoQuery.addGeoQueryEventListener( new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String key, GeoLocation location) {

        String UserID = key;

        if (!UserID.equals( auth.getUid() )) {
            db.collection( "Users" ).document( UserID ).collection( "MyItems" ).get().addOnCompleteListener( task_count -> {
                if (task_count.isSuccessful()) {
                    for (DocumentSnapshot document_near : task_count.getResult()) {
                        itemset.add( new DiscoverItems( document_near.getString( "ItemID" ) ) );
                    }
                }
            } );
        }
        List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(new HashSet<>(itemset));
        for (DiscoverItems item: itemsWithoutDuplicates){
            items.add(item);
        }
    discoverItemAdapter = new DiscoverItemAdapter(items, listener);
    rv_NearMeItems.setAdapter(discoverItemAdapter);
    }

但这不起作用,因为如果我有 2 个用户,onKeyEntered 将被调用两次。对于第一个用户,它将添加到 itemset 让我们说 4 个不相同的项目,一切都会好的。然后它会调用第二个用户,它也会向项目集中添加 3 个不相同的项目,这样就可以了。

我错过了什么吗? 因为使用上面的代码我得到了多个项目。

谢谢

我不知道你对象的复杂度,但你可以尝试将 List<> int 更改为 Set<>。一般来说,Set 是包含 没有重复元素的集合 (例如,基于他们的哈希码)。

1) 对象比较

首先,您必须覆盖 DiscoverItems class 中的 equals()hashCode() 才能使用基于散列的集合(如 HashSet)。

您可以在 Android Studio 中生成这些方法,并根据您可以说“这两个对象相同”的字段来选择。有时不需要比较所有字段(例如,您可以仅使用名称或某些 ID)。

你的情况,你必须比较你传递给 DiscoverItems class 的构造函数的这个字段。它看起来像那里:

@Override
public boolean equals(Object object) {
    if (this == object) return true;
    if (object == null || getClass() != object.getClass()) return false;
    DiscoverItems that = (DiscoverItems) object;
    return Objects.equals(itemID, that.itemID);
}

@Override
public int hashCode() {
    return Objects.hash(itemID);
}

2) 合集

因此更改为:

List<DiscoverItems> items = new ArrayList<>();

进入:

Set<DiscoverItems> items = new HashSet<>();

当你需要在一个地方检查时,你可以转换:

List ---> Set ---> List

例如:

Set<DiscoverItems> set = new HashSet<>(items);

if (items.size() == set.size()) {
    // No duplicates, use original list
} else {
    // Duplicates removed, use new list
    List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(set);
}

或没有附加条件:

Set<DiscoverItems> set = new HashSet<>(items);
List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(set);

或单行:

List<DiscoverItems> itemsWithoutDuplicates = new ArrayList<>(new HashSet<>(items));

提示

您应该将 class 命名为 DiscoverItem 而不是 DiscoverItems。因为代表的是一件,不是很多。