在多个数组上获取相同的元素值

时间:2022-01-15 10:02:46

Ive been searching SO about this question and most only have the problem with two arrays comparing by have a nested loop. My problem is quite the same but on a bigger scale. Suppose I have a 100 or thousand user on my app, and each user has the list of item it wants. Something like this

我一直在搜索关于这个问题的问题,并且大多数只有两个数组比较的问题有一个嵌套循环。我的问题非常相似,但规模更大。假设我的应用程序中有100或1000个用户,并且每个用户都有他想要的项目列表。像这样的东西

    User1 = {apple,orange,guava,melon,durian}
    User2 = {apple, melon,banana,lemon,mango}
    User3 = {orange,carrots,guava,melon,tomato}
    User4 = {mango,carrots,tomato,apple,durian}
    .
    .
   Nuser = ...

I wanted to see how many apples or oranges was listed from all the users array. So I am basically comparing but on a bigger scale. The data isn't static as well, A user can input an unknown fruit from the developers knowledge but on the users knowledge they can put it there so there can be multiple users that can put this unknown fruit and yet the system can still figure out how many is this unknown item was listed. Keep in mind this is a dynamic one. User can reach for example a 100 users depending how popular an app would be. I can't afford to do nested loop here.

我想看看所有用户数组中列出了多少苹果或橙子。所以我基本上比较但是规模更大。数据也不是静态的,用户可以从开发人员的知识中输入未知的水果,但是根据用户的知识,他们可以把它放在那里,这样可以有多个用户可以放置这个未知的水果,但系统仍然可以弄清楚这个未知项目被列出了多少。请记住,这是一个动态的。根据应用程序的受欢迎程度,用户可以达到例如100个用户。我不能在这里做嵌套循环。

PS this is not the exact problem but it is the simplest scenario I can think of to explain my problem.

PS这不是确切的问题,但它是我能想到解释我的问题的最简单的场景。

PS: just to clarify, I dont intend to use 3rd party lib as well like guava. I am having a problem on proguard with it.

PS:只是为了澄清,我不打算像番石榴一样使用第三方库。我在proguard上遇到了问题。

3 个解决方案

#1


5  

Edit

Just read that Original poster cannot use Java 8, which is a pity, because this would realy make it very easy!

只是看到原始海报不能使用Java 8,这是一个遗憾,因为这将真的很容易!

Java 7 solution

final Map<String, Integer> occurencesByFruit = new HashMap<>();
for (User user : users) {
    String[] fruits = user.getFruits();
    for (String fruit : fruits) {
        final Integer currentCount = occurencesByFruit.get(fruit);
        if (currentCount == null) {
            occurencesByFruit.put(fruit, 1);
        } else {
            occurencesByFruit.put(fruit, currentCount + 1);
        }
    }
}

Java 8 solution

I'd stream the users, flatMap() to the actual fruit elements, and then use Collectors.groupingBy() with a downstream collector Collectors.counting().

我将用户flatMap()流式传输到实际的水果元素,然后将Collectors.groupingBy()与下游收集器Collectors.counting()一起使用。

This will give you a Map where the keys are the fruits, and the values are the occurrences of each fruit throughout all your users.

这将为您提供一个映射,其中键是水果,值是所有用户中每个水果的出现次数。

List<User> users = Arrays.asList(/* ... */);

final Map<String, Long> occurencesByFruit = users.stream()
        .map(User::getFruits)
        .flatMap(Arrays::stream)
        .collect(Collectors.groupingBy(f -> f, Collectors.counting()));

#2


2  

Seems it is a good possibility to use HashMap<Item, Integer> fruits. You could iterate over all Users (you would need to store all Users in some kind of list, such as ArrayList<User> users) and check the list of items chosen by each User (I suppose User should have a field ArrayList<Item> items in its body to store items). You could achieve it with something like that:

似乎很有可能使用HashMap fruits。您可以迭代所有用户(您需要将所有用户存储在某种列表中,例如ArrayList 用户)并检查每个用户选择的项目列表(我想用户应该有一个字段ArrayList 其身体中的物品来存放物品)。你可以用这样的东西来实现它: ,integer>

for (User user : users) { // for each User from users list
    for (Item item : user.items) { // check each item chosen by this user
        if (fruits.containsKey(item) { // if the fruit is already present in the items HashMap increment the amount of items
            int previousNumberOfItems = fruits.get(item);
            fruits.put(item, ++previousNumberOfItems);
        else { // otherwise put the first occurrency of this item
            fruits.put(item, 1);
        }
    }
} 

#3


1  

I would either create an ArrayList containing a HashMap with strings and ints or use two ArrayLists (one of type String and one of type Integer). Then you can iterate over every entry in each of the user arrays (this is only a simple nested loop). For every entry in the current user array you check if there is already the same entry in the ArrayList you created additionally. If so, you increment the respective int. If not, you add a string and an int. In the end, you have the number of occurrences of all the fruit strings in the added ArrayLists, which is, if I understood you correctly, just what you wanted.

我要么创建一个包含带字符串和整数的HashMap的ArrayList,要么使用两个ArrayLists(一个是String类型,一个是Integer类型)。然后,您可以迭代每个用户数组中的每个条目(这只是一个简单的嵌套循环)。对于当前用户数组中的每个条目,检查是否已在另外创建的ArrayList中存在相同的条目。如果是这样,则增加相应的int。如果没有,则添加字符串和int。最后,您可以在添加的ArrayLists中找到所有水果字符串的出现次数,如果我理解正确的话,那就是您想要的。

#1


5  

Edit

Just read that Original poster cannot use Java 8, which is a pity, because this would realy make it very easy!

只是看到原始海报不能使用Java 8,这是一个遗憾,因为这将真的很容易!

Java 7 solution

final Map<String, Integer> occurencesByFruit = new HashMap<>();
for (User user : users) {
    String[] fruits = user.getFruits();
    for (String fruit : fruits) {
        final Integer currentCount = occurencesByFruit.get(fruit);
        if (currentCount == null) {
            occurencesByFruit.put(fruit, 1);
        } else {
            occurencesByFruit.put(fruit, currentCount + 1);
        }
    }
}

Java 8 solution

I'd stream the users, flatMap() to the actual fruit elements, and then use Collectors.groupingBy() with a downstream collector Collectors.counting().

我将用户flatMap()流式传输到实际的水果元素,然后将Collectors.groupingBy()与下游收集器Collectors.counting()一起使用。

This will give you a Map where the keys are the fruits, and the values are the occurrences of each fruit throughout all your users.

这将为您提供一个映射,其中键是水果,值是所有用户中每个水果的出现次数。

List<User> users = Arrays.asList(/* ... */);

final Map<String, Long> occurencesByFruit = users.stream()
        .map(User::getFruits)
        .flatMap(Arrays::stream)
        .collect(Collectors.groupingBy(f -> f, Collectors.counting()));

#2


2  

Seems it is a good possibility to use HashMap<Item, Integer> fruits. You could iterate over all Users (you would need to store all Users in some kind of list, such as ArrayList<User> users) and check the list of items chosen by each User (I suppose User should have a field ArrayList<Item> items in its body to store items). You could achieve it with something like that:

似乎很有可能使用HashMap fruits。您可以迭代所有用户(您需要将所有用户存储在某种列表中,例如ArrayList 用户)并检查每个用户选择的项目列表(我想用户应该有一个字段ArrayList 其身体中的物品来存放物品)。你可以用这样的东西来实现它: ,integer>

for (User user : users) { // for each User from users list
    for (Item item : user.items) { // check each item chosen by this user
        if (fruits.containsKey(item) { // if the fruit is already present in the items HashMap increment the amount of items
            int previousNumberOfItems = fruits.get(item);
            fruits.put(item, ++previousNumberOfItems);
        else { // otherwise put the first occurrency of this item
            fruits.put(item, 1);
        }
    }
} 

#3


1  

I would either create an ArrayList containing a HashMap with strings and ints or use two ArrayLists (one of type String and one of type Integer). Then you can iterate over every entry in each of the user arrays (this is only a simple nested loop). For every entry in the current user array you check if there is already the same entry in the ArrayList you created additionally. If so, you increment the respective int. If not, you add a string and an int. In the end, you have the number of occurrences of all the fruit strings in the added ArrayLists, which is, if I understood you correctly, just what you wanted.

我要么创建一个包含带字符串和整数的HashMap的ArrayList,要么使用两个ArrayLists(一个是String类型,一个是Integer类型)。然后,您可以迭代每个用户数组中的每个条目(这只是一个简单的嵌套循环)。对于当前用户数组中的每个条目,检查是否已在另外创建的ArrayList中存在相同的条目。如果是这样,则增加相应的int。如果没有,则添加字符串和int。最后,您可以在添加的ArrayLists中找到所有水果字符串的出现次数,如果我理解正确的话,那就是您想要的。