嵌套迭代器是否可以预期在循环会中断的地方
Is nesting iterators inside each other expectable where for loops would break
你认为像这样嵌套迭代器是好是坏?
上下文: for 循环版本中断,因为我在 for 循环中使用它的同时附加了同义词。
// HashSet inside HashMap
HashMap<String, HashSet<String>> synonyms = new HashMap<String, HashSet<String>>();
// loops through synonyms
Iterator word = synonyms.keySet().iterator();
while(word.hasNext()) {
// loops through synonyms
Iterator line = synonyms.get(word.next().toString()).iterator();
while(line.hasNext()) {
// adds to Synonyms, this breaks for loop version
addToSynonyms(word, line.next())
}
}
或者在 for 循环版本中,我可以制作 HashMap 的副本并将副本提供给 for 循环并仅附加原始版本,但上面的内容会更干净吗?
谢谢
希望在下面编辑一个更好的例子。
import java.util.Iterator;
import java.util.HashSet;
import java.util.HashMap;
// examples of looping through HashMap<String, HashSet<String>> numbersAndWords;
//
public class Example {
HashMap<String, HashSet<String>> numbersAndWords;
public Example() {
numbersAndWords = new HashMap<String, HashSet<String>>();
// data
numbersAndWords.put("five", new HashSet<>());
numbersAndWords.get("five").add(("1 2 3 4 5"));
}
/**
* uses two iterators to loop through numbersAndWords and adds to numbersAndWords without breaking loops
*/
public void exampleOne() {
// loops through HashMap Strings of words "five"
Iterator words = numbersAndWords.keySet().iterator();
while(words.hasNext()) {
// loops through HashSet Strings of numbers "1 2 3 4 5"
Iterator numbers = numbersAndWords.get(words.next().toString()).iterator();
while(numbers.hasNext()) {
// data is arbitrary reason for exmaple is this appends
// numbersAndWords which breaks the for loop
// Their for I have to use an iterator but should I be using to
// or have things in a different format
numbersAndWords.put("three", new HashSet<>());
numbersAndWords.get("three").add(("1, 2, 3"));
numbers.next();
}
}
}
public static void main(String[] args) {
Example example = new Example();
example.exampleOne();
}
}
目前正在研究使用 HashMap.size() 将第一个 itr 替换为 for 循环,这样当我稍后附加 HashMap 时它不会中断。
谢谢
即使在最近的更新之后,这段代码的目的仍然有点模糊。
如果需要创建一些新数据并将其附加到原始地图numbersAndWords
,并且它们以某种方式依赖于原始地图的当前状态,然后必须创建并填充一个新的临时地图(使用增强的 for
循环,使用 map/flatMap
的 Stream API,等等)。完成后,可以使用 Map::putAll
:
将此新地图的内容添加到原始地图中
public void exampleOne() {
Map<String, HashSet<String>> toAppend = new HashMap<>();
for (Map.Entry<String, HashSet<String>> me : numbersAndWords.entrySet()) {
for (String str : me.getValue()) {
System.out.println("Appending for key: " + me.getKey() + "; value=" + str);
toAppend.computeIfAbsent("three", k -> new HashSet<>())
.add("1 2 3"); // or whatever is really needed
}
}
numbersAndWords.putAll(toAppend);
System.out.println(numbersAndWords);
}
假设原图是这样设置的:
public Example() {
numbersAndWords = new HashMap<String, HashSet<String>>();
// data
numbersAndWords.computeIfAbsent("five", k -> new HashSet<>()).add("1 2 3 4 5");
numbersAndWords.computeIfAbsent("five", k -> new HashSet<>()).add("5 4 3 2 1");
numbersAndWords.computeIfAbsent("four", k -> new HashSet<>()).add("1 2 3 4");
}
调用时输出如下new Example().exampleOne();
:
Appending for key: four; value=1 2 3 4
Appending for key: five; value=1 2 3 4 5
Appending for key: five; value=5 4 3 2 1
{four=[1 2 3 4], five=[1 2 3 4 5, 5 4 3 2 1], three=[1 2 3]}
但是,这种硬编码值的填充是毫无意义的,因为不能在映射中为硬编码键创建重复的条目,并且将相同的值添加到集合中也是无用的。
你认为像这样嵌套迭代器是好是坏?
上下文: for 循环版本中断,因为我在 for 循环中使用它的同时附加了同义词。
// HashSet inside HashMap
HashMap<String, HashSet<String>> synonyms = new HashMap<String, HashSet<String>>();
// loops through synonyms
Iterator word = synonyms.keySet().iterator();
while(word.hasNext()) {
// loops through synonyms
Iterator line = synonyms.get(word.next().toString()).iterator();
while(line.hasNext()) {
// adds to Synonyms, this breaks for loop version
addToSynonyms(word, line.next())
}
}
或者在 for 循环版本中,我可以制作 HashMap
谢谢
希望在下面编辑一个更好的例子。
import java.util.Iterator;
import java.util.HashSet;
import java.util.HashMap;
// examples of looping through HashMap<String, HashSet<String>> numbersAndWords;
//
public class Example {
HashMap<String, HashSet<String>> numbersAndWords;
public Example() {
numbersAndWords = new HashMap<String, HashSet<String>>();
// data
numbersAndWords.put("five", new HashSet<>());
numbersAndWords.get("five").add(("1 2 3 4 5"));
}
/**
* uses two iterators to loop through numbersAndWords and adds to numbersAndWords without breaking loops
*/
public void exampleOne() {
// loops through HashMap Strings of words "five"
Iterator words = numbersAndWords.keySet().iterator();
while(words.hasNext()) {
// loops through HashSet Strings of numbers "1 2 3 4 5"
Iterator numbers = numbersAndWords.get(words.next().toString()).iterator();
while(numbers.hasNext()) {
// data is arbitrary reason for exmaple is this appends
// numbersAndWords which breaks the for loop
// Their for I have to use an iterator but should I be using to
// or have things in a different format
numbersAndWords.put("three", new HashSet<>());
numbersAndWords.get("three").add(("1, 2, 3"));
numbers.next();
}
}
}
public static void main(String[] args) {
Example example = new Example();
example.exampleOne();
}
}
目前正在研究使用 HashMap.size() 将第一个 itr 替换为 for 循环,这样当我稍后附加 HashMap 时它不会中断。
谢谢
即使在最近的更新之后,这段代码的目的仍然有点模糊。
如果需要创建一些新数据并将其附加到原始地图numbersAndWords
,并且它们以某种方式依赖于原始地图的当前状态,然后必须创建并填充一个新的临时地图(使用增强的 for
循环,使用 map/flatMap
的 Stream API,等等)。完成后,可以使用 Map::putAll
:
public void exampleOne() {
Map<String, HashSet<String>> toAppend = new HashMap<>();
for (Map.Entry<String, HashSet<String>> me : numbersAndWords.entrySet()) {
for (String str : me.getValue()) {
System.out.println("Appending for key: " + me.getKey() + "; value=" + str);
toAppend.computeIfAbsent("three", k -> new HashSet<>())
.add("1 2 3"); // or whatever is really needed
}
}
numbersAndWords.putAll(toAppend);
System.out.println(numbersAndWords);
}
假设原图是这样设置的:
public Example() {
numbersAndWords = new HashMap<String, HashSet<String>>();
// data
numbersAndWords.computeIfAbsent("five", k -> new HashSet<>()).add("1 2 3 4 5");
numbersAndWords.computeIfAbsent("five", k -> new HashSet<>()).add("5 4 3 2 1");
numbersAndWords.computeIfAbsent("four", k -> new HashSet<>()).add("1 2 3 4");
}
调用时输出如下new Example().exampleOne();
:
Appending for key: four; value=1 2 3 4
Appending for key: five; value=1 2 3 4 5
Appending for key: five; value=5 4 3 2 1
{four=[1 2 3 4], five=[1 2 3 4 5, 5 4 3 2 1], three=[1 2 3]}
但是,这种硬编码值的填充是毫无意义的,因为不能在映射中为硬编码键创建重复的条目,并且将相同的值添加到集合中也是无用的。