给出类似表格的数据结构,例如arraylists的arraylist(2D数组,或其他一些可迭代的数据结构),根据特定规则检查元素的最简洁方法是什么?
例如,给出以下数据:
[true, false, false, true]
[false, false, false, false]
[true, false, false, false]
如何强制满足以下三个条件之一:
true
false
true
,否则验证必须失败。 例如,由于位置[0,3]中的true
值,上述数据不得通过验证。
更新:
显然,在Java 8中避免循环的一种方法是使用myBoolArrayList.stream().allMatch(Boolean::booleanValue);
和myBoolArrayList.stream().noneMatch(Boolean::booleanValue)
; - 这将覆盖前两个条件,对第三个条件还不是很清楚。
答案 0 :(得分:2)
请注意,通过一起查看的三个规则,您无需进行单独检查:
列表只能包含all-true或all-false,但如果其中任何一个有效,则组合规则是“all( boolean )值必须相同”,可以在像!booleanList.contains(!booleanList.get(0))
这样的单个表达式。但是还有第三种选择:
如果一行包含混合值,则只有第一个元素可以为true,否则验证必须失败。
这基本上说:如果有false
值,除了第一个元素之外的所有元素也必须为假。这条规则使另外两个过时了:
false
值,则所有值均为true
false
值,则第一个元素可能为true,因此所有值false
都是此规则的特例false
值,则第一个元素的值无关紧要因此,我们可以通过查看除第一个之外的任何其他元素来缩短测试,例如,在索引1
并根据该值选择一个要测试的规则:
true
,所有值必须为真false
,则除了第一个值之外的所有值都必须为false
因此整个条件可以表示为
list.size()<2 ||
list.get(1)? // has a TRUE at a position other than the first
!list.contains(false): // all are TRUE
!list.subList(1, list.size()).contains(true); // all except the first are FALSE
关于Stream API,
!list.contains(x)
可以表示为list.stream().noneMatch(Predicate.isEqual(x))
和!list.subList(1, list.size()).contains(x)
可以表示为list.stream().skip(1).noneMatch(Predicate.isEqual(x))
,但是没有理由在这里使用Stream API。
但是,要验证List
List
,您可以使用Stream API检查所有子列表是否符合条件:
static boolean validate(List<List<Boolean>> list2D) {
return list2D.stream().allMatch(list-> list.size()<2 ||
list.get(1)? !list.contains(false): !list.subList(1, list.size()).contains(true)
);
}
答案 1 :(得分:1)
您可以使用Guava库来检查列表,例如:
[更新时间:根据反馈...我认为这不是最好的方式,但这是一种做法。
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class ValidationTest {
@Test
public void test() {
// Here is the initial table, you can play with it.
List<List<Boolean>> list = new ArrayList<List<Boolean>>() {{
add(new ArrayList<Boolean>() {{
add(false);
add(false);
add(false);
add(false);
}});
add(new ArrayList<Boolean>() {{
add(true);
add(false);
add(false);
add(false);
}});
add(new ArrayList<Boolean>() {{
add(true);
add(true);
add(true);
add(true);
}});
}};
boolean checkBooleanRule = this.checkBooleanRule(list);
Assert.assertTrue("The table is invalid", checkBooleanRule);
}
private boolean checkRow(List<Boolean> row, final boolean value) {
// If checking everything is true/false, let's just find if there is a False = !value
return row.contains(!value);
}
private boolean checkBooleanRule(final List<List<Boolean>> inputList) {
// Gets the row that brake the rule!
Optional<List<Boolean>> invalidRow = Iterables.tryFind(inputList, new Predicate<List<Boolean>>() {
@Override
public boolean apply(List<Boolean> inputRow) {
if (!checkRow(inputRow, true))
return false;
if (!checkRow(inputRow, false))
return false;
return (inputRow.get(0) ? checkRow(inputRow.subList(1, inputRow.size()), false) : true);
}
});
// If Present, then, the Table is invalid! == There is a row with a false!
return !invalidRow.isPresent();
}
}
答案 2 :(得分:0)
这是使用Java Lambda表达式执行此操作的一种方法。参考文献What is the best way to filter a Java Collection?
感谢评论
import java.util.ArrayList;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
ArrayList<Boolean> array = new ArrayList<Boolean>();
array.add(true);
array.add(true);
array.add(true);
array.add(false);
//the simplest to read way
Stream<Boolean> arrayChecker = array.stream().filter(a -> a == true);
//Checks if the stream filter is equal to the array size. If so then all true
System.out.println(arrayChecker.count() == array.size() );
//the better way thanks to @ccpizza
Stream<Boolean> arrayChecker = array.stream().filter(Boolean::booleanValue);
//Even better way
array.stream().allMatch(Boolean::booleanValue);
//so basic I missed it. Thanks to @Holger
System.out.println(! array.contains(false));
}
}