我想使用 Java流将ArrayList<String>
转换为Set<ScopeItem>
。
ScopeItem is a enum;
items is an ArrayList<String>;
Set<ScopeItem> scopeItems = items.stream()
.map(scopeString -> ScopeItem.valueOf(scopeString))
.filter(Objects::nonNull)
.collect(Collectors.toSet());
在枚举中没有的字符串中会抛出以下内容:
java.lang.IllegalArgumentException: No enum const...
理想情况下,我想跳过任何不匹配的字符串。
我想也许是使用flatmap?任何想法怎么做?
答案 0 :(得分:3)
您可以将以下方法添加到ScopeItem
:
public static ScopeItem valueOfOrNull(String name) {
try {
return valueOf(name);
} catch (IllegalArgumentException e) {
// no such element
return null;
}
}
并使用它来映射枚举值:
.map(scopeString -> ScopeItem.valueOfOrNull(scopeString))
非空值(您已经拥有)的后续.filter()
将过滤掉与不匹配字符串对应的空值。
答案 1 :(得分:1)
您可以在map
内添加try-catch以返回null
,而不是抛出异常:
Set<ScopeItem> scopeItems = items.stream()
.map(scopeString ->
{
try
{
return ScopeItem.valueOf(scopeString);
}
catch (IllegalArgumentException e)
{
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toSet());
您也可以事先使用filter
来检查值数组是否包含您要查找的字符串:
Set<ScopeItem> scopeItems = items.stream()
.filter(scopeString -> Arrays.stream(ScopeItem.values())
.anyMatch(scopeItem -> scopeItem.name().equals(scopeString)))
.map(ScopeItem::valueOf)
.collect(Collectors.toSet());
答案 2 :(得分:1)
与其他人不同,我不推荐使用例外,因为我觉得它们应该用于特殊情况,而不是用于可能发生的事情。一个简单的解决方案是使用一组可接受的字符串静态集合,并简单地检查一下你要使用valueOf
的字符串是否在所述集合中。
package test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class Test {
public static enum ScopeItem {
ScopeA,
ScopeB;
private static Set<String> castableStrings;
static {
castableStrings = new HashSet<>();
for (ScopeItem i : ScopeItem.values()) {
castableStrings.add(i.name());
}
}
public static boolean acceptable(String s) {
return castableStrings.contains(s);
}
}
public static void main(String[] args) {
List<String> items = Arrays.asList("ScopeA", "RandomString", "ScopeB");
Set<ScopeItem> scopeItems = items.stream()
.filter(ScopeItem::acceptable)
.map(ScopeItem::valueOf)
.collect(Collectors.toSet());
System.out.println(scopeItems.size());
}
}
答案 3 :(得分:1)
这里有一种更优雅的方法。您不必为枚举添加任何新字段;你也可以简单地对 it 运行一个流,并确定你的收藏中是否有任何匹配。
以下代码假定枚举声明为:
enum F {
A, B, C, D, E
}
并且看起来如此:
List<String> bad = Arrays.asList("A", "a", "B", "b", "C", "c");
final Set<F> collect = bad.stream()
.filter(e -> Arrays.stream(F.values())
.map(F::name)
.anyMatch(m -> Objects.equals(e, m)))
.map(F::valueOf)
.collect(Collectors.toSet());
这里要注意两个部分:
F::name
将其映射到字符串。Objects.equals
在这里使用空值做正确的事情)答案 4 :(得分:0)
您可以使用Apache Common's commons-lang3 EnumUtils.getEnum()代替gcc -Wall -std=gnu99 fileTest.c -o fileTest
。如果没有匹配的枚举条目(然后您可以在代码中完全过滤),则返回null。
答案 5 :(得分:0)
最简单,最清晰的方法是在values()
上过滤您的枚举items.contains()
方法:
Set<ScopeItem> enumVals = Arrays.stream(ScopeItem.values())
.filter(e -> items.contains(e.name()))
.collect(Collectors.toSet());
没有添加任何功能只是为了让流做你想做的事情,而且这一目了然很明显。