0

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

    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.

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

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.

7
  • What part of this are you stuck with? Commented Jan 10, 2018 at 7:17
  • The one with multiple array comparing all the element Commented Jan 10, 2018 at 7:18
  • To clarify, you you want search through all users and count how many times a specific fruit appears. Commented Jan 10, 2018 at 7:22
  • Yes, exactly like that. Commented Jan 10, 2018 at 7:23
  • You could use ArrayList to hold each user and use streams to count the occurances. It's difficult to determine an implementation as it's unclear what Object each fruit is. Commented Jan 10, 2018 at 7:28

3 Answers 3

5

Edit

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

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().

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()));
Sign up to request clarification or add additional context in comments.

1 Comment

That was what I had first, but this made the else case less clear: occurencesByFruit.put(fruit, occurenceByFruit.get(fruit) + 1). But I can't say which of the 2 is better
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:

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);
        }
    }
} 

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.