【问题标题】:Counting appearance while using LinkedHashSet使用 LinkedHashSet 时计数外观
【发布时间】:2020-08-09 22:26:48
【问题描述】:

我有一个 XML 文件,我需要在其中查找并计算年份标签的出现次数。 例如:

Found year 2020 10 times.
Found year 2017 1 times.
Found year 2019 2 times. 
(...)

为了避免重复使用 HashSet 的年份。 代码:

public class Publications {
    public static void main(String[] args) throws IOException {
        Set<String> publicationYears = new LinkedHashSet<>();
        try (BufferedReader reader = Files.newBufferedReader(Paths.get("dblp-2020-04-01.xml"))) {
            Pattern pattern = Pattern.compile("<year>(.+?)</year>", Pattern.DOTALL);
            for (String line; (line = reader.readLine()) != null; ) {
                Matcher matcher = pattern.matcher(line);
                if (matcher.find()) {
                    String year = matcher.group(1);
                    publicationYears.add(year);
                }
            }
        }

结果:

2010
2002
1992
1994
1993
2006(...)

但现在我找不到有效的代码来计算每年的出现次数。创建一个多维数组然后搜索会很慢。有什么建议吗?

【问题讨论】:

  • 您是否想过使用地图来跟踪每年的计数?
  • @njzk2 我认为这是一个可能的解决方案,但我以前从未从事过这个工作。我不知道如何实现
  • 使用地图而不是集合,例如使用map.set(year, map(getOrDefault(year, 0) + 1)而不是set.add(year)

标签: java arrays xml hash


【解决方案1】:

试试这个:

  • 我用地图替换了集合。
  • 完成这项工作的语句是
        count.compute(year, (k,v)->v == null ? 1 : v + 1); 
  • 如果它第一次遇到它的年份,它只会为年份添加 1,否则它会在该年份添加 1。
   Map<String, Integer> count = new LinkedHashMap<>();
        try (BufferedReader reader = Files.newBufferedReader(Paths.get("dblp-2020-04-01.xml"))) {
            Pattern pattern = Pattern.compile("<year>(.+?)</year>", Pattern.DOTALL);
            for (String line; (line = reader.readLine()) != null; ) {
                Matcher matcher = pattern.matcher(line);
                if (matcher.find()) {
                    String year = matcher.group(1);
                    count.compute(year, (k,v)->v == null ? 1 : v + 1);
                }
            }
        }
    }

要打印出来,请执行以下操作

count.entrySet().forEach(System.out::println);

【讨论】:

    【解决方案2】:

    有很多方法可以做到这一点。其中一些如下:

    1. 将所有年份添加到 List 并使用 Collections.frequency,如下所示:
    import java.util.Collections;
    import java.util.LinkedHashSet;
    import java.util.List;
    import java.util.Set;
    
    public class Main {
        public static void main(String[] args) {
            List<Integer> years = List.of(2010, 2011, 2013, 2010, 2012, 2010, 2011, 2010, 2014);
            Set<Integer> yearSet = new LinkedHashSet<Integer>(years);
            for (Integer year : yearSet) {
                System.out.println("Found year " + year + " " + Collections.frequency(years, year) + " times");
            }
        }
    }
    

    输出:

    Found year 2010 4 times
    Found year 2011 2 times
    Found year 2013 1 times
    Found year 2012 1 times
    Found year 2014 1 times
    
    1. 将所有年份添加到List,然后创建频率如下的Map
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    
    public class Main {
        public static void main(String[] args) {
            List<Integer> years = List.of(2010, 2011, 2013, 2010, 2012, 2010, 2011, 2010, 2014);
            Map<Integer, Integer> frequencyMap = new LinkedHashMap<Integer, Integer>();
            for (Integer year : years) {
                if (frequencyMap.get(year) == null) {
                    frequencyMap.put(year, 1);
                } else {
                    frequencyMap.put(year, frequencyMap.get(year) + 1);
                }
            }
            for (Entry<Integer, Integer> entry : frequencyMap.entrySet()) {
                System.out.println("Found year " + entry.getKey() + " " + entry.getValue() + " times");
            }
        }
    }
    

    输出:

    Found year 2010 4 times
    Found year 2011 2 times
    Found year 2013 1 times
    Found year 2012 1 times
    Found year 2014 1 times
    
    1. 将所有年份添加到List,然后使用Map::merge 创建频率Map,如下所示:
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    
    public class Main {
        public static void main(String[] args) {
            List<Integer> years = List.of(2010, 2011, 2013, 2010, 2012, 2010, 2011, 2010, 2014);
            Map<Integer, Integer> frequencyMap = new LinkedHashMap<Integer, Integer>();
            years.forEach(year -> frequencyMap.merge(year, 1, (oldValue, newValue) -> oldValue + newValue));
            for (Entry<Integer, Integer> entry : frequencyMap.entrySet()) {
                System.out.println("Found year " + entry.getKey() + " " + entry.getValue() + " times");
            }
        }
    }
    

    输出:

    Found year 2010 4 times
    Found year 2011 2 times
    Found year 2013 1 times
    Found year 2012 1 times
    Found year 2014 1 times
    

    【讨论】:

      猜你喜欢
      • 2012-08-12
      • 1970-01-01
      • 2014-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多