0

I have a problem where I want to keep the original arraylist and want to make two separate arraylist where one doesn't contain any duplicates and the other the amount of items in the first arraylist. For example:

ArrayList<Item> items = new ArrayList<Item>(); 
ArrayList<Item> items2 = new ArrayList<Item>(); 
ArrayList<Item> occurences = new ArrayList<Item>();

items[0, 1, 2] would have bandana bandana bandana
items2[0] would have bandana
occurences[0] would have 3

7 Answers7

0

Below code shows an example of what you need but instead of Item (I don't know if you put it as example or it's your class) there are String to store elements and Integer for occurences.

To store elements without duplicates I suggest to use Set

public static void main(String[] args) {
    ArrayList<String> items = new ArrayList<String>(); 
    ArrayList<String> items2 = new ArrayList<String>(); 
    ArrayList<Integer> occurences = new ArrayList<Integer>();

    items.add("bandana");
    items.add("bandana");
    items.add("bandana");

    items2.addAll(new HashSet<>(items)); // create Hashset to remove duplicates and add again to Arraylist
    occurences.add(items.size()); // add size of items list as first element

    items.forEach(System.out::println);   // Print: "bandana" "bandana" "bandana"
    items2.forEach(System.out::println);  // Print: "bandana"
    occurences.forEach(System.out::println); // Print: 1
}
Rafał Sokalski
  • 1,817
  • 2
  • 17
  • 29
0

This is probably not the most efficient way of doing it but I would try something like this:

ArrayList<Item> items = new ArrayList<Item>(); 
ArrayList<Item> items2 = new ArrayList<Item>(); 
ArrayList<Item> occurences = new ArrayList<Item>();

for(int i=0; i<items.size(); i++)
{
    Item x = items.get(i);
    int count=1;

    if(!items2.contains(x))
    {
        items2.add(x);
        for(int j=i+1; j<items.size(); j++)
        {
            if(items2.get(j)==x)
                count++;
        }
        ocurrences.add(count);
    }
}

You might want to change Item to int for the occurrences list.

MkGm7
  • 53
  • 5
0

No Duplicates in Collection

For the collection that should have no duplicate Items, use a Set<Item> instead of an ArrayList<Item>. The Set data structure will not store duplicates. Since Item is a custom object you created, you will need to override the hashCode and equals method in your Item class.

This approach is O(1) - which is way better than keep an ArrayList<Item> and iterating it and searching for a duplicate (which will be O(n) at worst).

Occurrences

For the occurrences problem, instead of keeping your items in an ArrayList<Item>, keep them in a Map<Item,Integer>. This will map the item to how many occurrences there are of it.

Using the map, you will need to get the key, which is the Item you are about to add. If it already exists in the map, simply add one to the value of that key (the occurrences number).

If they key doesn't exist yet (this is the first time this Item will be inserted into the map), simply add it to the map, and set the value as 1.

Using a map will also be a way more efficient solution, as it will also be O(1), instead of O(n) if an ArrayList<Item> will be used.

Example:

Set<Item> itemSet = new HashSet<>();
Map<Item,Integer> occurencesMap = new HashMap<>();

        itemSet.add(yourItem);
        itemSet.add(yourItem);
        itemSet.add(secondItem);
        //itemSet now contains only 2 objects!


        if (occurencesMap.get(yourItem) == null){
            occurencesMap.put(yourItem,1);
        }
        else{
            //adding 1 to the current value of occurences for that item.
            occurencesMap.get(yourItem)++;
        }
Daniel B.
  • 2,491
  • 2
  • 12
  • 23
0

Assuming you can use Java 8 streams you could also do it this way:

List<String> items = Arrays.asList("bandana", "helmet", "bandana",
                           "bandana", "silk hat", "basecap", "silk hat");

Map<String, Long> result = items.stream().collect(
    Collectors.groupingBy(Function.identity(), Collectors.counting()));

System.out.println(result); //prints {silk hat=2, helmet=1, bandana=3, basecap=1}

Instead of two lists with the distinct values and the occurences you will have a map with the item itself as key (Function.identity()) and the number of occurences as the value (Collectors.counting()).

C. Weber
  • 907
  • 5
  • 18
0

This is my solution using streams and lambda functions. I moddified occurence to be a Map<Item, Integer> so that we can count per item

items.stream().forEach( i -> {
    if (!items2.contains(i)) {
        items2.add(i);
    }
    occurences.merge(i, 1, Integer::sum);
});

The very cool use of merge was found in this answer. Since we don't know what Item i I tested this using String instead so equals etc worked properly

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
0

Using lambdas to get a list of distinct values:

ArrayList items2 = items.stream().distinct().collect(Collectors.toCollection(ArrayList::new)));

If I understood correctly you need the number of occurrences for each item:

Map<Item, Integer> m = new HashMap();
items.stream().forEach(k-> m.merge(k,1, Integer::sum));
ArrayList occurrences = new ArrayList(m.values());

The order in occurrences does not reflect the order of the items.

b0gusb
  • 4,283
  • 2
  • 14
  • 33
0

You can generate each list as below,

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;

public class Main
{
  public static void main(String args[])
  {
    ArrayList<String> items = new ArrayList<>();
    ArrayList<String> items2 = new ArrayList<>();
    ArrayList<Integer> occurrences = new ArrayList<>();

    items.addAll(Arrays.asList("bandana", "bandana", "bandana", "abc", "abc"));

    items2.addAll(new LinkedHashSet<>(items));

    for (String item : items2)
    {
      occurrences.add(Collections.frequency(items, item));
    }

    System.out.println(items);
    System.out.println(items2);
    System.out.println(occurrences);
  }
}
Sandeepa
  • 3,457
  • 5
  • 25
  • 41