访问Java 8 Lambda表达式内的字段

时间:2018-11-02 12:25:13

标签: java java-8 java-stream

Am正在编写线性搜索实现。我也使用Java 7和8编写了代码。

下面是我的代码:

int[] arr = new int[] { 12, 34, 94, 8, 37, 10 };
System.out.println("Enter the element to search: ");
Scanner scan = new Scanner(System.in);
int element = scan.nextInt();
boolean found = false;

// Linear search implementation using Java 7 features
for (int i = 0; i < arr.length; i++) {
    if (element == arr[i]) {
        int n = element;
        System.out.println("Element : "+n+" has been found at the index : "+i);
        found = true;
        break;
    }
}

// Linear search implementation using Java 8 features
IntStream.range(0, arr.length)
    .forEach(i -> {
        if (element == arr[i]) {
            int n = element;
            System.out.println("Element : " + n + " has been found at the index : " + i);
            found = true;
            break;
        }
    });

if (!found) {
    System.out.println("Element : "+ element + " not found.");
}

以下代码正常工作:

for (int i = 0; i < arr.length; i++) {
    if (element == arr[i]) {
        int n = element;
        System.out.println("Element : " + n + " has been found at the index : " + i);
        found = true;
        break;
    }
}

但是,下面具有Java 8功能的代码为forEach循环内的字段抛出错误

IntStream.range(0, arr.length)
    .forEach(i -> {
        if (element == arr[i]) {
            int n = element;
            System.out.println("Element : " + n + " has been found at the index : " + i);
            found = true;
            break;
        }
    });

发生错误:

  

在封闭范围内定义的局部变量必须是最终的或实际上是最终的

     

break不能在循环或开关之外使用

如何在Java 8功能的forEach块中访问boolean found

3 个答案:

答案 0 :(得分:5)

实际上该消息已经说明了。请注意,在使用流时,通常会尝试避免使用.forEach(或者至少不只是将for循环转换为.forEach)。

您可能想要的是以下内容:

IntStream.range(0, arr.length)
        .filter(i -> element == arr[i]) // .equals( ??
        .findFirst()
        .ifPresent(i -> System.out.println("Element : "+element+" has been found at the index : "+i));

如果您还必须处理找不到的情况,请使用以下命令:

OptionalInt result = IntStream.range(0, arr.length)
        .filter(i -> element == arr[i]) // .equals( ??
        .findFirst();
if (result.isPresent()) {
  System.out.printf("Element : %s has been found at the index : %d%n", element, result.getAsInt());
} else {
  // none found
  System.out.printf("Element %s not found%n", element);
}

较新的Java版本支持ifPresentOrElse,例如在此处可能有用。 (由MC Emperor测试的代码,因为我在这里没有Java> 8;-)):

...
.findFirst()
.ifPresentOrElse(i -> System.out.printf("Element : %s has been found at the index : %d%n", element, i),
                () -> System.out.printf("Element %s not found%n", element));

答案 1 :(得分:1)

您不应访问boolean found,而应从流中返回该值。

int element;
OptionalInt valueOptional = Arrays.stream(arr)
                                 .filter(current -> current == element)
                                 .findFirst();

然后,检查天气是否存在可选项。

valueOptional.isPresent();

答案 2 :(得分:1)

有多种方法可以执行此操作,具体取决于您的具体要求:

索引

您当然可以创建一个包含给定数组的所有索引的IntStream.range(0, arr.length)

element

然后您可以检查给定位置的元素是否等于 .filter(i -> arr[i] == element)

element

如果发现任何等于 .findAny() 的数组元素,我们可以中止步行:

OptionalInt

这将返回一个OptionalInt,其中包含找到的元素的第一个索引。 -1设计为包含值或不包含值。这比使用哨兵值(例如 .ifPresent(i -> System.out.println("Element " + element + " found at index " + i)) )更好。

如果找到该值,则可以执行某些操作:

Arrays

无需使用索引即可流式传输元素

如果您不关心实际索引,也可以直接流式处理数组。 java.util包中的int[]类提供了一种流int并返回IntStream的方法,该流是设计用来流Arrays.stream(arr) .filter(t -> t == element) .findAny() .ifPresent(t -> ...); 的源的流。

Arrays.stream(arr).findAny()

有关流的更多信息

流元素被延迟消耗。这意味着如果消耗了足够的元素以达到最终结果,则流终止。例如,arr仅触摸findAny()的第一个元素。您可以说if (found) { break; }的作用类似于forEach


请注意,您实际上正在使用lambda expression。那是Java 8中引入的一种新的语言构造。Consumer只不过是接受forEach的方法,而该方法又是functional interface。您只能access variables which are final or effectively finalfor方法不同于break循环,因此您实际上不能使用function loadScript(url, callback){ var script = document.createElement("script") script.type = "text/javascript"; if (script.readyState){ //IE script.onreadystatechange = function(){ if (script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; callback(); } }; } else { //Others script.onload = function(){ callback(); }; } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); } loadScript("https://cdnjs.cloudflare.com/ajax/libs/Faker/3.1.0/faker.min.js", function(){ //initialization code alert('loaded: ' + faker.name.findName()); });