我收到了此表单
的无序列表class Element {
String property; // has value from the set ("A", "B", "C", "D")
}
其中没有两个元素具有相同的property
值
我想根据一组规则选择一个元素,如下所示,并返回其property
值:
property
具有值"A"
,则选择该元素。property
具有值"B"
,则选择该元素。property
具有值"C"
,则选择该元素。这是我为此问题提出的一个解决方案:
String chooseElementProperty(List<Element> elements) {
// Iterates the list and creates a set of all the property values.
// example: [{property: 'A'}, {property: 'B'}] -> {'A', 'B'}
Set<String> propertyValues = pluckPropertyValues(elements);
if (propertyValues.contains("A"))
return "A";
if (propertyValues.contains("B"))
return "B";
if (propertyValues.contains("C"))
return "C";
throw new IllegalArgumentException("Invalid input!");
}
我的问题是:有什么更好/更干净的方法可以让这种方法更具可扩展性,如果将来我想选择"B"
超过"A"
,我会更容易改变我的偏好?
答案 0 :(得分:4)
不是将所需的属性值硬编码到chooseElementProperty
中,而是在另一个参数中提供它们:
String chooseElementProperty(List<Element> elements, List<String> prefs) {
// Iterates the list and creates a set of all the property values.
// example: [{property: 'A'}, {property: 'B'}] -> {'A', 'B'}
Set<String> propertyValues = pluckPropertyValues(elements);
for (String s: prefs) {
if (propertyValues.contains(s))
return s;
}
throw new IllegalArgumentException("Invalid input!");
}
我在这里使用了List<String>
,但如果您愿意,也可以使用String[]
甚至String...
varargs。
答案 1 :(得分:3)
试试这个:
List<String> targets = Arrays.asList("A", "B", "C");
return elements.stream()
.map(this::pluckPropertyValues)
.flatMap(Set::stream)
.filter(targets::contains)
.sorted(Comparator.comparing(targets::indexOf))
.findFirst()
.orElseThrow(IllegalArgumentException::new);
这适用于任意目标列表,其偏好基于它们在列表中的位置。
免责声明:代码可能无法编译或工作,因为它在我的手机上被翻阅(但它有可能起作用)
答案 2 :(得分:3)
假设所有属性值都是字母,您可以对列表进行排序并提供comparator
按propery
排序,然后验证第一项的属性
Collections.sort(elements, new Comparator<Element>() {
@Override
public int compare(Element a, Element b) {
return a.property.compareTo(b.property);
}
});
List<String> check = Arrays.asList("A", "B", "C");
String tmp = elements.get(0).property;
if check.contains(tmp)
return tmp
else
throw new IllegalArgumentException("Invalid input!");
您还可以使用lambda进行排序:
Collections.sort(elements, (e1, e1) -> e1.property.compareTo(e2.property));
答案 3 :(得分:2)
目前的答案似乎假设订单是"A", "B", "C"
,因此可能忽略了最后一个重要的陈述:
如果以后我想选择
"B"
超过"A"
,那么这种方法可以更容易地改变我的偏好,那么这种方法更好/更干净的方法是什么?
除此之外,解决方案可能被视为......&#34;棘手&#34; ......或者从计算的角度看是复杂的。我投票选择与您类似的解决方案,但没有创建属性列表,并且基本上只是将首选项放入列表中以迭代它:
import java.util.Arrays;
import java.util.List;
class Element
{
String property;
Element(String property)
{
this.property = property;
}
}
public class PickByPreference
{
public static void main(String[] args)
{
List<Element> elements = Arrays.asList(
new Element("B"),
new Element("C"),
new Element(null),
new Element("A"));
System.out.println(chooseElementProperty(elements));
}
static String chooseElementProperty(List<Element> elements)
{
// Change this to change the preferences
// (or pass it in as a parameter)
List<String> preferences = Arrays.asList("A", "B", "C");
for (String preference : preferences)
{
for (Element element : elements)
{
if (preference.equals(element.property))
{
return element.property;
}
}
}
throw new IllegalArgumentException("Invalid input!");
}
}
编辑:就渐近复杂性而言,将属性提取到Set
可能是有益的,特别是如果你有许多元素。在这种情况下,实现将是
static String chooseElementProperty(List<Element> elements)
{
// Change this to change the preferences
// (or pass it in as a parameter)
List<String> preferences = Arrays.asList("A", "B", "C");
Set<String> propertyValues = pluckPropertyValues(elements);
for (String preference : preferences)
{
if (propertyValues.contains(preference))
{
return element.property;
}
}
throw new IllegalArgumentException("Invalid input!");
}
答案 4 :(得分:1)
之前的答案是正确的。
我的两分钱是为了避免contains()
使用indexOf()
所以使用
if (propertyValues.indexOf("A") > -1)
return "A";
if (propertyValues.indexOf("B") > -1)
return "B";
if (propertyValues.indexOf("C") > -1)
return "C";