基于 HashMap 更新 List 元素 value/key
Update a List element based on a HashMap value/key
我有 ArrayList:
List<String> wordsList = new ArrayList<>();
// [eu, quero, voltar, para, praia, e, comer, queijo]
和 HashMap:
Map<String, String> wordsMap = new HashMap<>();
//{v.=voltar, c.=comer, q.=queijo., p.=praia}
我想做的是:如果列表元素等于映射值,则用映射 key 替换列表元素。在此示例中,结果将是:
// [eu, quero, v., para, p., e, c., q.]
我试过的是
for (String word : wordsList) {
for (Map.Entry<String, String> entry : wordsMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (word.equals(value)) {
newWordsList.add(key);
} else {
newWordsList.add(word);
}
}
}
Result: [eu, eu, eu, eu, quero, quero, quero, quero, v., voltar, voltar, voltar, para, para, para, para, praia, praia, praia, p., e, e, e, e, comer, c., comer, comer, queijo, queijo, q., queijo]
有什么帮助吗??谢谢!
给定列表和地图:
List<String> wordsList = Arrays.asList("eu", "quero", "voltar", "para", "praia", "e", "comer", "queijo");
Map<String, String> wordsMap = Map.of("v.", "voltar", "c.", "comer", "q.", "queijo", "p.", "praia");
然后下面的代码 returns 你的结果(没有任何外部依赖):
// If the list element is equal to map value, then replace the list element
// by the map key.In this example, the result would be:
wordsMap.values().stream()
// If the list contains the map value
.filter(wordsList::contains)
.forEach(value -> {
// Find the corresponding map key
String mapKey = wordsMap.entrySet()
.stream()
.filter(entry -> Objects.equals(entry.getValue(), value))
.map(Map.Entry::getKey) // It could find several keys if you have the same value for different keys
.findFirst()
.orElseThrow(); // It should never happen as we are looping in the map values
// Find the index and update the list with the map key
int index = wordsList.indexOf(value);
wordsList.set(index, mapKey);
});
System.out.println(wordsList);
// [eu, quero, v., para, p., e, c., q.]
我会使用 google HashBiMap 因为它可以提供同一地图的反向视图,即在 Map<K,V>
中你可以同时执行这两项操作 get(K) returns V
和 get(V) returns K
// Form the words list
List<String> wordsList = new ArrayList<String>();
wordsList.add("eu");
wordsList.add("quero");
// etc adding all of the terms you mentioned
// Form the keyset
HashBiMap<String, String> wordsMap = HashBiMap.create();
wordsMap.put("v", "voltar");
wordsMap.put("c", "comer");
// etc adding all the terms you mentioned
List<String> wordsListOut = new ArrayList<String>();
// Iterating through the wordsList
for (int i = 0; i < wordsList.size(); i++) {
// Get the current element
String element = wordsList.get(i);
// Does it have an inverse pair?
String result = wordsMap.inverse().get(element);
// If it has an inverse pair, add the inverse key. Otherwise, add the element raw.
wordsListOut.add(result == null ? element : result);
}
// Outputs: [eu, quero, v, para, p, e, c, q]
System.out.println(wordsListOut);
HashBiMap 的依赖是GoogleGuava:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
对我来说,第一步是创建一个使用值作为键并使用键作为值的新映射。这比遍历旧地图并检查值要容易得多。
Map<String, String> invertedWordsMap = wordsMap.entrySet().stream().collect(Collecotrs.toMap(Map.Entry::getValue), Map.Entry::getKey));
//{voltar=v., comer=c., queijo=q.., praia=p.}
然后我只需要检查地图中是否存在密钥
for (int i = 0; i < wordsList.size(); i++) {
String word = invertedWordsMap.get(wordsList.get(i));
if (word != null) {
wordsList.set(i, word);
}
}
这是强制性的花式流答案。请记住,如果您使用流解决方案,旧列表将被替换而不是更改。
wordsList = wordsList.stream().map(word -> invertedWordsMap.getOrDefault(word, word)).collect(Collectors.toList());
您可以简单地迭代 wordsMap.entrySet()
,在 wordsList
中找到 entry#value
的索引,并使用 entry#key
在索引处更新 wordsList
.
演示:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
List<String> wordsList = new ArrayList<>(
List.of("eu", "quero", "voltar", "para", "praia", "e", "comer", "queijo."));
Map<String, String> wordsMap = Map.of("v.", "voltar", "c.", "comer", "q.", "queijo.", "p.", "praia");
for (Map.Entry<String, String> entry : wordsMap.entrySet()) {
int index = wordsList.indexOf(entry.getValue());
if (index != -1) {
wordsList.set(index, entry.getKey());
}
}
System.out.println(wordsList);
}
}
输出:
[eu, quero, v., para, p., e, c., q.]
注意: List#indexOf
returns 指定元素在这个列表中第一次出现的索引,或者 -1
如果这个列表不包含该元素。因此,上面给出的解决方案中的逻辑会检查 -1
,并且只会替换第一次出现的匹配值。如果你的列表有重复的元素并且你想要替换所有出现的匹配值,你需要找到匹配值的所有索引并替换它们,如下所示:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
List<String> wordsList = new ArrayList<>(List.of("eu", "quero", "queijo.", "voltar", "queijo.", "para", "praia",
"e", "queijo.", "comer", "queijo."));
Map<String, String> wordsMap = Map.of("v.", "voltar", "c.", "comer", "q.", "queijo.", "p.", "praia");
for (Map.Entry<String, String> entry : wordsMap.entrySet()) {
List<Integer> allIndices = allIndicesOf(wordsList, entry.getValue());
for (int index : allIndices) {
wordsList.set(index, entry.getKey());
}
}
System.out.println(wordsList);
}
static List<Integer> allIndicesOf(List<String> list, String str) {
return IntStream.range(0, list.size())
.boxed()
.filter(i -> list.get(i).equals(str))
.collect(Collectors.toList());
}
}
输出:
[eu, quero, q., v., q., para, p., e, q., c., q.]
我有 ArrayList:
List<String> wordsList = new ArrayList<>();
// [eu, quero, voltar, para, praia, e, comer, queijo]
和 HashMap:
Map<String, String> wordsMap = new HashMap<>();
//{v.=voltar, c.=comer, q.=queijo., p.=praia}
我想做的是:如果列表元素等于映射值,则用映射 key 替换列表元素。在此示例中,结果将是:
// [eu, quero, v., para, p., e, c., q.]
我试过的是
for (String word : wordsList) {
for (Map.Entry<String, String> entry : wordsMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (word.equals(value)) {
newWordsList.add(key);
} else {
newWordsList.add(word);
}
}
}
Result: [eu, eu, eu, eu, quero, quero, quero, quero, v., voltar, voltar, voltar, para, para, para, para, praia, praia, praia, p., e, e, e, e, comer, c., comer, comer, queijo, queijo, q., queijo]
有什么帮助吗??谢谢!
给定列表和地图:
List<String> wordsList = Arrays.asList("eu", "quero", "voltar", "para", "praia", "e", "comer", "queijo");
Map<String, String> wordsMap = Map.of("v.", "voltar", "c.", "comer", "q.", "queijo", "p.", "praia");
然后下面的代码 returns 你的结果(没有任何外部依赖):
// If the list element is equal to map value, then replace the list element
// by the map key.In this example, the result would be:
wordsMap.values().stream()
// If the list contains the map value
.filter(wordsList::contains)
.forEach(value -> {
// Find the corresponding map key
String mapKey = wordsMap.entrySet()
.stream()
.filter(entry -> Objects.equals(entry.getValue(), value))
.map(Map.Entry::getKey) // It could find several keys if you have the same value for different keys
.findFirst()
.orElseThrow(); // It should never happen as we are looping in the map values
// Find the index and update the list with the map key
int index = wordsList.indexOf(value);
wordsList.set(index, mapKey);
});
System.out.println(wordsList);
// [eu, quero, v., para, p., e, c., q.]
我会使用 google HashBiMapMap<K,V>
中你可以同时执行这两项操作 get(K) returns V
和 get(V) returns K
// Form the words list
List<String> wordsList = new ArrayList<String>();
wordsList.add("eu");
wordsList.add("quero");
// etc adding all of the terms you mentioned
// Form the keyset
HashBiMap<String, String> wordsMap = HashBiMap.create();
wordsMap.put("v", "voltar");
wordsMap.put("c", "comer");
// etc adding all the terms you mentioned
List<String> wordsListOut = new ArrayList<String>();
// Iterating through the wordsList
for (int i = 0; i < wordsList.size(); i++) {
// Get the current element
String element = wordsList.get(i);
// Does it have an inverse pair?
String result = wordsMap.inverse().get(element);
// If it has an inverse pair, add the inverse key. Otherwise, add the element raw.
wordsListOut.add(result == null ? element : result);
}
// Outputs: [eu, quero, v, para, p, e, c, q]
System.out.println(wordsListOut);
HashBiMap 的依赖是GoogleGuava:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
对我来说,第一步是创建一个使用值作为键并使用键作为值的新映射。这比遍历旧地图并检查值要容易得多。
Map<String, String> invertedWordsMap = wordsMap.entrySet().stream().collect(Collecotrs.toMap(Map.Entry::getValue), Map.Entry::getKey));
//{voltar=v., comer=c., queijo=q.., praia=p.}
然后我只需要检查地图中是否存在密钥
for (int i = 0; i < wordsList.size(); i++) {
String word = invertedWordsMap.get(wordsList.get(i));
if (word != null) {
wordsList.set(i, word);
}
}
这是强制性的花式流答案。请记住,如果您使用流解决方案,旧列表将被替换而不是更改。
wordsList = wordsList.stream().map(word -> invertedWordsMap.getOrDefault(word, word)).collect(Collectors.toList());
您可以简单地迭代 wordsMap.entrySet()
,在 wordsList
中找到 entry#value
的索引,并使用 entry#key
在索引处更新 wordsList
.
演示:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
List<String> wordsList = new ArrayList<>(
List.of("eu", "quero", "voltar", "para", "praia", "e", "comer", "queijo."));
Map<String, String> wordsMap = Map.of("v.", "voltar", "c.", "comer", "q.", "queijo.", "p.", "praia");
for (Map.Entry<String, String> entry : wordsMap.entrySet()) {
int index = wordsList.indexOf(entry.getValue());
if (index != -1) {
wordsList.set(index, entry.getKey());
}
}
System.out.println(wordsList);
}
}
输出:
[eu, quero, v., para, p., e, c., q.]
注意: List#indexOf
returns 指定元素在这个列表中第一次出现的索引,或者 -1
如果这个列表不包含该元素。因此,上面给出的解决方案中的逻辑会检查 -1
,并且只会替换第一次出现的匹配值。如果你的列表有重复的元素并且你想要替换所有出现的匹配值,你需要找到匹配值的所有索引并替换它们,如下所示:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
List<String> wordsList = new ArrayList<>(List.of("eu", "quero", "queijo.", "voltar", "queijo.", "para", "praia",
"e", "queijo.", "comer", "queijo."));
Map<String, String> wordsMap = Map.of("v.", "voltar", "c.", "comer", "q.", "queijo.", "p.", "praia");
for (Map.Entry<String, String> entry : wordsMap.entrySet()) {
List<Integer> allIndices = allIndicesOf(wordsList, entry.getValue());
for (int index : allIndices) {
wordsList.set(index, entry.getKey());
}
}
System.out.println(wordsList);
}
static List<Integer> allIndicesOf(List<String> list, String str) {
return IntStream.range(0, list.size())
.boxed()
.filter(i -> list.get(i).equals(str))
.collect(Collectors.toList());
}
}
输出:
[eu, quero, q., v., q., para, p., e, q., c., q.]