Как проверить hashset на наличие существующего элемента, а затем добавить счетчик

#java #hashset #distinct-values

#java #hashset #различные значения

Вопрос:

Я новичок в Java и начинаю изучать, как использовать hashsets. У меня проблема с моим практическим упражнением. Цель состоит в том, чтобы удалить дублирующее описание, а затем добавить количество похожих описаний.

Например, у меня есть,

Информатика — 15
Инженерия — 20
Стоматология — 10
Архитектура — 11
Информатика — 25
Стоматология — 7

тогда вывод должен быть только:

Информатика — 40
Инженерия — 20
Стоматология — 17
Архитектура — 11

 import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Arrays;

public class Main {
  public static void main(String[] args) {
    //printing summary report
    ArrayList<String>   summaryReport=  new ArrayList<String>();

    final String[] CourseDesc           = {"Computer Science", "Architecture", "Dentistry", "Computer Science"};
    final int[] CourseCount         = {15, 10, 10, 25};

    for (String element: CourseDesc) {
        for(int el: CourseCount){
             summaryReport.add(element   " "  el);
        }
     }
   System.out.println(summaryReport);
  }
}
  

Я просто застрял на том, как добавить количество похожих описаний. Спасибо!

Комментарии:

1. Не могли бы вы поделиться своим полным примером кода, пожалуйста?

2. полный код состоит из тысячи строк

3. Но вы ведь не написали «тысячи строк», не так ли? Пожалуйста, поделитесь написанным вами кодом. Трудно понять, зачем вам здесь нужен HashSet, HashMap выглядит гораздо более подходящим решением проблемы.

4. Вы должны поделиться рабочим примером своей проблемы, чтобы мы могли его воспроизвести.

5. Я уже скопировал часть полного кода, с которым у меня возникла проблема

Ответ №1:

Разумным способом решения вашей проблемы было бы использовать Java Streams:

 final String[] courseDesc = {"Computer Science", "Engineering", "Dentistry", "Architecture", "Computer Science", "Dentistry"};
final int[] courseCount = {15, 20, 10, 11, 25, 7};

Map<String, Integer> summaryReport = IntStream.range(0, courseDesc.length).boxed()
    .collect(Collectors.toMap(
        index -> courseDesc[index], index -> courseCount[index],
        (count0, count1) -> count0   count1, LinkedHashMap::new
    ));
  

Это создает карту с курсом в качестве ключа и суммой в качестве значения. Если карта содержит курс, и тот же курс собирается снова, лямбда-выражение (count0, count1) -> count0 count1 обрабатывает его путем суммирования значений. LinkedHashMap::new Заключается в поддержании порядка.

Теперь вы можете распечатать сводку следующим образом:

 summaryReport.forEach((course, count) -> System.out.println(course   " - "   count));
  

Результат:

 Computer Science - 40
Engineering - 20
Dentistry - 17
Architecture - 11
  

Ответ №2:

Из OP я вижу, что вам нужен ассоциативный контейнер ключ-значение, поэтому наиболее очевидным способом будет использование Map , проверьте, присутствует ли значение в виде ключа, если нет — добавьте его с помощью 1 счетчика, если присутствует — добавьте 1 :

 void test() {
    Map<String, Integer> summaryReport = new HashMap<>();
    String curDesc = "whatever";

    Integer count = summaryReport.get(curDesc);
    if (count == null) {
        summaryReport.put(curDesc, 1);
    } else {
        summaryReport.put(curDesc, count   1);
    }
}
  

Поступая более сложным способом, вы можете использовать mutable AtomicInteger в качестве счетчика:

 void test() {
    Map<String, AtomicInteger> summaryReport = new HashMap<>();
    AtomicInteger counter = summaryReport.putIfAbsent("whatever", new AtomicInteger(0));
    if (counter != null) {
        counter.incrementAndGet();
    }
}