我正在编写一个项目,该项目从 .java 文件中捕获 Java 关键字并使用地图跟踪出现的情况。我过去成功地使用过类似的方法,但我似乎无法将这种方法用于我的预期用途。
Map<String,Integer> map = new TreeMap<String,Integer>(); Set<String> keywordSet = new HashSet<String>(Arrays.asList(keywords)); Scanner input = new Scanner(file); int counter = 0; while (input.hasNext()) { String key = input.next(); if (key.length() > 0) { if (keywordSet.contains(key)) { map.put(key, 1); counter++; } if(map.containsKey(key)) <--tried inner loop here, failed { int value = map.get(key); value++; map.put(key, value); } }
这段代码应该将关键字添加到键中,并在每次出现相同键时递增值。到目前为止,它添加了关键字,但未能正确增加值。这是一个示例输出:
{assert=2, class=2, continue=2, default=2, else=2, ...}
基本上它会增加地图中的每个值,而不是它应该增加的值。我不确定我是在想这个还是什么。我尝试了一个内部循环,它给了我疯狂的结果。我真的希望我只是想多了。任何帮助是极大的赞赏!
有一种更简洁(也更容易推理)的方式来实现你想要的:
final ConcurrentMap<String, AtomicInteger> map = new ConcurrentHashMap<>(); final Scanner input = new Scanner(file); while (input.hasNext()) { final String key = input.next(); if (key.length() > 0) { map.putIfAbsent(key, new AtomicInteger(0)); map.get(key).incrementAndGet(); } }
让我们分析一下为什么会这样。
每当Scanner遇到关键字时,有两种可能的情况:您以前遇到过(即,它是已知关键字),或者它是尚未见过的关键字。
Scanner
putIfAbsent
AtomicInteger
incrementAndGet()
然后,如果您想要密钥集,请执行以下操作:
final Set<String> keys = map.keySet();
要打印所有值,您可以执行以下操作:
for (final String k : map.keySet()) { System.out.println(k + ": " + map.get(k).get()); }
您不会被迫使用我在上面使用的两个“不同”类,ConcurrentMap并且AtomicInteger. 使用它们更容易,因为它们封装了您尝试自己编写的大部分逻辑(但失败了)。他们封装的逻辑正是所有其他答案所描述的(即,测试该值是否存在,如果不将其设置为 0,则获取存在的任何值,将其递增并将其放回地图中)。
ConcurrentMap
要按字母顺序维护地图的键(我们的单词被计算在内),请使用ConcurrentNavigableMap诸如ConcurrentSkipListMap.
ConcurrentNavigableMap
ConcurrentSkipListMap