使用Java在数组对象中打印所有重复的项目

发布于 2025-02-07 00:39:46 字数 512 浏览 3 评论 0 原文

我想知道如何在一系列对象中打印所有重复的项目。对于Ex:

[
   {
      "key": "KEY1",
      "value": "123",
    },
    {
      "key": "KEY2",
      "value": "234",
    },
    {
       "key": "KEY1",
       "value": "456"
    }
]

代码:我有此逻辑,但它将排除第一次出现Key1,并且仅打印它的重复。

Set<String> duplicates = new HashSet();
..for(i in items)..{
  if (duplicates.contains(i.val())) {
     System.out.println('duplicates found');
  }
}

我想打印两个项目如下:

找到的重复项目,[key1]带值[“ 123”,“ 456”]

I would like to know how to print all repeated items in an array of objects. For ex:

[
   {
      "key": "KEY1",
      "value": "123",
    },
    {
      "key": "KEY2",
      "value": "234",
    },
    {
       "key": "KEY1",
       "value": "456"
    }
]

code: I have this logic but it will exclude the first occurrence of KEY1 and prints only a duplicate of it.

Set<String> duplicates = new HashSet();
..for(i in items)..{
  if (duplicates.contains(i.val())) {
     System.out.println('duplicates found');
  }
}

I want to print both items as below:

duplicate items found, [KEY1] with values ["123", "456"]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心意如水 2025-02-14 00:39:46

我认为,对于您试图实现 map&lt; string,list&lt; gt;&gt; 而不是 hashset&lt; string&gt; 。实际上, set 只会告诉您键是否已包含在 set 中,但它不会跟踪特定键是多少值绑定到。

这是一个实现,将密钥对象用作 MAP 的密钥,其值添加到 MAP 的值列表中:

class MyObject {
    private String key;
    private String value;

    //... contrustcor & getters ...
}

public class Main {
    public static void main(String[] args) {
        MyObject[] items = new MyObject[]{new MyObject("KEY1", "123"), new MyObject("KEY2", "234"), new MyObject("KEY1", "456")};
        HashMap<String, List<String>> map = new HashMap<>();

        for (MyObject obj : items) {
            if (!map.containsKey(obj.getKey())) {
                map.put(obj.getKey(), new ArrayList<>(List.of(obj.getValue())));
            } else {
                map.get(obj.getKey()).add(obj.getValue());
            }
        }

        for (Map.Entry<String, List<String>> e : map.entrySet()) {
            if (e.getValue().size() > 1) {
                System.out.printf("Duplicate items found, %s with values %s%n", e.getKey(), e.getValue());
            }
        }
    }
}

相反,如果您需要添加数据结构中的实际对象,然后无论使用 hashset hashmap ,您的课程都需要通过为该一般的等价和哈希码合同来尊重一般的等价合同,以提供适当的定义相应的方法。

https://docs.oracle。 com/javase/7/docs/api/java/lang/object.html#hashcode()

实际上, hashset 在引擎盖下使用 hashmap ,因此在两种情况下都必须覆盖所述方法。这是因为 hashmap 是作为一个存储库实现的,其中每个条目都基于密钥的 hashcode()将每个条目存储在存储桶中。但是,不同的键可能会产生相同的哈希码,因此可以在同一存储桶中列出多个条目。那时, hashmap 必须诉诸 equals()方法,以在一个对应于输入的条目的存储桶中找到确切的键,以检索或替换元素。这就是为什么提供 hashcode() equals()方法的正确定义的正确定义如此至关重要的原因。

在您的情况下,可能的实现可能是:

class MyObject {
    private String key;
    private String value;

   //... contrustcor & getters ...

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MyObject myObject = (MyObject) o;
        return Objects.equals(key, myObject.key);
    }

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

    @Override
    public String toString() {
        return value;
    }
}

public class Main {
    public static void main(String[] args) {
        MyObject[] items = new MyObject[]{new MyObject("KEY1", "123"), new MyObject("KEY2", "234"), new MyObject("KEY1", "456")};
        HashMap<MyObject, List<MyObject>> map = new HashMap<>();

        for (MyObject obj : items) {
            if (!map.containsKey(obj)) {
                map.put(obj, new ArrayList<>(List.of(obj)));
            } else {
                map.get(obj).add(obj);
            }
        }

        for (Map.Entry<MyObject, List<MyObject>> e : map.entrySet()) {
            if (e.getValue().size() > 1) {
                System.out.printf("Duplicate items found, %s with values %s%n", e.getKey().getKey(), e.getValue());
            }
        }
    }
}

I think that for what you're trying to achieve a Map<String, List<String>> would be better suited rather than a HashSet<String>. In fact, a Set would only tell you whether a key is already contained in the Set or not, but it won't keep track of how many values a particular key is bound to.

Here is an implementation where the key's object is used as the key for the Map and its value added to the Map's list of values:

class MyObject {
    private String key;
    private String value;

    //... contrustcor & getters ...
}

public class Main {
    public static void main(String[] args) {
        MyObject[] items = new MyObject[]{new MyObject("KEY1", "123"), new MyObject("KEY2", "234"), new MyObject("KEY1", "456")};
        HashMap<String, List<String>> map = new HashMap<>();

        for (MyObject obj : items) {
            if (!map.containsKey(obj.getKey())) {
                map.put(obj.getKey(), new ArrayList<>(List.of(obj.getValue())));
            } else {
                map.get(obj.getKey()).add(obj.getValue());
            }
        }

        for (Map.Entry<String, List<String>> e : map.entrySet()) {
            if (e.getValue().size() > 1) {
                System.out.printf("Duplicate items found, %s with values %s%n", e.getKey(), e.getValue());
            }
        }
    }
}

Instead, if you need to add the actual object within the data structure, then regardless of using a HashSet or a HashMap, your class needs to honor the general equals and hashcode contracts by providing a proper definition for the corresponding methods.

https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()

In fact, a HashSet uses a HashMap under the hood, so in both cases is necessary to override said methods. This is because a HashMap is implemented as an array of buckets, where each entry is stored within a bucket based on the key's hashCode(). However, different keys may yield same hashcodes, so multiple entries may be listed within a same bucket. At that point, the HashMap has to resort to the equals() method to find the exact key within a bucket which corresponds to the inputted entry in order to retrieve or replace an element. This is why it is so crucial to provide a proper definition of the hashCode() and equals() methods.

https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html

In your case, a possible implementation could be:

class MyObject {
    private String key;
    private String value;

   //... contrustcor & getters ...

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MyObject myObject = (MyObject) o;
        return Objects.equals(key, myObject.key);
    }

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

    @Override
    public String toString() {
        return value;
    }
}

public class Main {
    public static void main(String[] args) {
        MyObject[] items = new MyObject[]{new MyObject("KEY1", "123"), new MyObject("KEY2", "234"), new MyObject("KEY1", "456")};
        HashMap<MyObject, List<MyObject>> map = new HashMap<>();

        for (MyObject obj : items) {
            if (!map.containsKey(obj)) {
                map.put(obj, new ArrayList<>(List.of(obj)));
            } else {
                map.get(obj).add(obj);
            }
        }

        for (Map.Entry<MyObject, List<MyObject>> e : map.entrySet()) {
            if (e.getValue().size() > 1) {
                System.out.printf("Duplicate items found, %s with values %s%n", e.getKey().getKey(), e.getValue());
            }
        }
    }
}
ι不睡觉的鱼゛ 2025-02-14 00:39:46

准备 hashmap list 喜欢 hashmap&lt; string,list&lt; string&gt;&gt;

if(!map.contains(key)) {
    map.put(key,new ArrayList<String>());
} 
map.get(key).add(value);

最后,您可以迭代hashmap,检查arraylist size&gt; 1是否并使用arraylist打印消息

Prepare a HashMap of List like HashMap<String,List<String>>

if(!map.contains(key)) {
    map.put(key,new ArrayList<String>());
} 
map.get(key).add(value);

In the end, you can iterate HashMap, check if the ArrayList size >1 and print the message with ArrayList

走野 2025-02-14 00:39:46

尝试一下。

static void printAllRepeatedItems(Item[] items) {
    Arrays.stream(items)
        .collect(groupingBy(Item::key, mapping(Item::value, toList())))
        .entrySet().stream()
        .filter(e -> e.getValue().size() > 1)
        .forEach(e -> System.out.printf("duplicate items found, %s with values %s%n",
            e.getKey(), e.getValue()));
}

Item[] items = {
    new Item("KEY1", "123"), 
    new Item("KEY2", "234"),
    new Item("KEY1", "456"),
};
printAllRepeatedItems(items);

输出:

duplicate items found, KEY1 with values [123, 456]

Try this.

static void printAllRepeatedItems(Item[] items) {
    Arrays.stream(items)
        .collect(groupingBy(Item::key, mapping(Item::value, toList())))
        .entrySet().stream()
        .filter(e -> e.getValue().size() > 1)
        .forEach(e -> System.out.printf("duplicate items found, %s with values %s%n",
            e.getKey(), e.getValue()));
}

And

Item[] items = {
    new Item("KEY1", "123"), 
    new Item("KEY2", "234"),
    new Item("KEY1", "456"),
};
printAllRepeatedItems(items);

output:

duplicate items found, KEY1 with values [123, 456]
短暂陪伴 2025-02-14 00:39:46

可以在一个语句中使用Java 8流:

import java.util.List;
import static java.util.stream.Collectors.*;

// ...

record Item(String key, String value) { }

List<String> items = List.of(
    new Item("KEY1", "123"),
    new Item("KEY2", "234"),
    new Item("KEY1", "456")
    );

// ...

items
.stream()
.collect(
    groupingBy(Item::key, 
        mapping(Item::value, toList())))   // Map<String, List<String>>
.entrySet()
.stream()
.filter(e -> e.getValue().size() > 1) // only duplicates
.map(e -> new Object[] {e.getKey(), e.getValue()})
.map("Duplicate items found, %s with values %s"::formatted)
.forEach(System.out::println);

替代方案,并有一些帮助者:

// same as above

Collector<Item, ?, Map<String, List<String>>> groupValuesByKey = 
    groupingBy(Item::key, mapping(Item::value, toList()));

Predicate<Entry<?, List<String>>> duplicated = 
    e -> e.getValue().size() > 1;

Function<Entry<?, ?>, String> entryToString = 
    e -> "Duplicate items found, %s with value %s".formatted(e.getKey(), e.getValue());

items
.stream()
.collect(groupValuesByKey)  // Map<String, List<String>>
.entrySet()
.stream()
.filter(duplicated)         // only duplicates
.map(entryToString)
.forEach(System.out::println);

Can be done in one statement using Java 8 streams:

import java.util.List;
import static java.util.stream.Collectors.*;

// ...

record Item(String key, String value) { }

List<String> items = List.of(
    new Item("KEY1", "123"),
    new Item("KEY2", "234"),
    new Item("KEY1", "456")
    );

// ...

items
.stream()
.collect(
    groupingBy(Item::key, 
        mapping(Item::value, toList())))   // Map<String, List<String>>
.entrySet()
.stream()
.filter(e -> e.getValue().size() > 1) // only duplicates
.map(e -> new Object[] {e.getKey(), e.getValue()})
.map("Duplicate items found, %s with values %s"::formatted)
.forEach(System.out::println);

Alternative, with some helpers:

// same as above

Collector<Item, ?, Map<String, List<String>>> groupValuesByKey = 
    groupingBy(Item::key, mapping(Item::value, toList()));

Predicate<Entry<?, List<String>>> duplicated = 
    e -> e.getValue().size() > 1;

Function<Entry<?, ?>, String> entryToString = 
    e -> "Duplicate items found, %s with value %s".formatted(e.getKey(), e.getValue());

items
.stream()
.collect(groupValuesByKey)  // Map<String, List<String>>
.entrySet()
.stream()
.filter(duplicated)         // only duplicates
.map(entryToString)
.forEach(System.out::println);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文