Как хранить дубликаты из массива с количеством - PullRequest
0 голосов
/ 11 января 2019

У меня проблема с тем, что я хочу сохранить первоначальный список и хочу создать два отдельных списка, где один не содержит дубликатов, а другой - количество элементов в первом списке. Например:

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 ]

0 голосов
/ 11 января 2019

Использование лямбда-выражений для получения списка различных значений:

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

Если я правильно понял, вам нужно количество вхождений для каждого элемента:

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

Заказ в occurrences не отражает порядок пунктов.

0 голосов
/ 11 января 2019

Вы можете создать каждый список, как показано ниже,

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);
  }
}
0 голосов
/ 11 января 2019

Это мое решение с использованием потоков и лямбда-функций. Я изменил occurence, чтобы он стал Map<Item, Integer>, чтобы мы могли считать за элемент

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

Очень крутое использование merge было найдено в этом ответе . Поскольку мы не знаем, что Item я протестировал, используя String, чтобы equals и т. Д. Работали правильно

0 голосов
/ 11 января 2019

Предполагая, что вы можете использовать потоки Java 8, вы также можете сделать это следующим образом:

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}

Вместо двух списков с различными значениями и вхождениями у вас будет карта с самим элементом в качестве ключа (Function.identity ()) и числом вхождений в качестве значения (Collectors.counting ()).

0 голосов
/ 11 января 2019

В коллекции нет дубликатов

Для коллекции, в которой не должно быть повторяющихся элементов, используйте Set<Item> вместо ArrayList<Item>. Структура данных Set не будет хранить дубликаты . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Таким образом, * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 10 * * * * * * * * * * * 10 *

Этот подход O (1) - что намного лучше, чем хранить ArrayList<Item> и повторять его и искать дубликат (который будет O (n) в худший случай).

Появления

При возникновении проблемы, вместо хранения ваших предметов в ArrayList<Item>, оставьте их в Map<Item,Integer>. Это сопоставит элемент с количеством его экземпляров.

Используя карту, вам необходимо получить ключ, который является Item, который вы собираетесь добавить. Если он уже существует на карте, просто добавьте его к значению этого ключа (номер вхождения).

Если их ключ еще не существует (это первый раз, когда Item будет вставлен в карту), просто добавьте его на карту и установите значение 1.

Использование карты также будет более эффективным решением, так как оно будет также O (1) вместо O (n) , если ArrayList<Item> будет б.

* +1039 * Пример:
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)++;
        }
0 голосов
/ 11 января 2019

Это, вероятно, не самый эффективный способ сделать это, но я бы попробовал что-то вроде этого:

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

Возможно, вы захотите изменить Item на int для списка вхождений.

0 голосов
/ 11 января 2019

Ниже приведен пример того, что вам нужно, но вместо Item (я не знаю, если вы поместите его в качестве примера или это ваш класс), есть String для хранения элементов и Integer для вхождений.

Для хранения элементов без дубликатов я предлагаю использовать 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
}
...