Java:如何检查二维列表/数组中的布尔条件?

时间:2016-04-06 16:41:52

标签: java arrays validation java-8

给出类似表格的数据结构,例如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); - 这将覆盖前两个条件,对第三个条件还不是很清楚。

3 个答案:

答案 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));
    }
}