【问题标题】:How to use an existing ArrayList inside Lambda Expression/block?如何在 Lambda 表达式/块中使用现有的 ArrayList?
【发布时间】:2021-05-11 11:07:41
【问题描述】:

我是 Java 8 的新手,正在尝试使用 Java 8 功能重写现有的代码 sn-p 逻辑。

但是,当将其放置在 lambda 块内时,我不确定如何使用在块外部定义的现有 arrayList 从中获取值。它抱怨它必须是最终的或实际上是最终的。

我从转换内部传统 for 循环开始,遇到了与计数器变量相同的问题,我可以使用 AtomicInteger 对其进行排序,但我不确定如何为 arrayList 执行此操作,而且我也无法在内部定义 arrayList lambda 块,因为它依赖于外部 while 循环中存在的 i 变量。

任何帮助将不胜感激!!!提前致谢。

下面是我的代码 sn-p :-


public String somemethod(ArrayList someValues){
        int i=0;
        String status="Failed";
        
        ArrayList someOtherValues = new ArrayList();
    try
    {
    while ( i < (someValues.size()))
        {
            someOtherValues = (ArrayList) someValues.get(i);
            someOtherValues.replaceAll(t -> Objects.isNull(t) ? "" : t); //converting every null to "" within the arrayList someOtherValues
            int count=4;
            AtomicInteger counter=new AtomicInteger(5);
            if(!someOtherValues.get(0).toString().equals(""))
            {
            while ( count < (someOtherValues.size()))
            {
                
                IntStream.range(0, 3).forEach(k -> {
                someObjectClass someObject=new someObjectClass();
                someOtherObjectClass id = new someOtherObjectClass(someOtherValues.get(0).toString(),someOtherValues.get(count).toString()) //Line where the error is
                someObject=new someObjectClass(id);
                 someObject.setId(id);
                 if(someCondition)
                 {
                     try
                     {
                     someObject.setSomething(someValue); 
                     counter.incrementAndGet()
                     }
                 }
                 someObject.setsomeOtherValues1(someOtherValues.get(1).toString());
                 someObject.setsomeOtherValues2(someOtherValues.get(3).toString())
                }
                 count=counter.get();
                 counter.incrementAndGet();

            }
            }
            i++;

    }
    catch(Exception e)
    {
        return status;
    }
             
        
}

现在它正在等待的地方是它抱怨 someOtherValues,它是在 lambda 块之外定义的现有 arrayList 需要是最终的或有效地最终的才能获取元素。

真的不可能使用 Java 8 流/lambdas/forEach 将上述函数更改/优化为更少的代码行吗?

【问题讨论】:

  • 请提供可以编译的代码,你的不行。但是是的,如果你在循环之外定义列表,它不是最终的,所以它不能在 lambdas 中使用。在循环中定义您的列表。
  • 该代码显然存在编译时错误,因为它不允许我继续,因为我必须将 arrayList "someOtherValues" 声明为 final,但这是不可能的。我什至不能在里面声明它,因为它是由someOtherValues = (ArrayList) someValues.get(i); 形成的,如果你能看到它在 while 循环内的 forEach 块之外。我正在寻找一些帮助,他们可以从字面上帮助我以 java 8 方式编写整个内容,而不会影响逻辑。谢谢!!!
  • 嗨。您能否输入导致错误的代码,也可以解释您期望的结果。有时您必须使用流重写方法而不是转换现有代码
  • 错误所在的行:``` someOtherObjectClass id = new someOtherObjectClass(someOtherValues.get(0).toString(),someOtherValues.get(count).toString()) //错误所在的行错误是```。我希望从某个地方调用此方法并返回一个状态,该状态需要不是失败的状态。我无法继续,因为我无法使用在 lambda forEach 块之外定义的现有数组列表,而不将其声明为 final 或使其有效地成为 final
  • 警告:您正在使用 原始类型(在您的情况下为 ArrayList)。 切勿使用原始类型,始终提供必要的类型参数。

标签: arraylist lambda java-8 java-stream java-ee-8


【解决方案1】:

一般来说,尝试更改 lambda 定义中的外部变量并不是一个好主意。但是由于Java对final字段和变量的概念非常松散,只适用于赋值,所以还是可以做到的。 在外部定义变量的 lambda 表达式中唯一不能做的事情是分配新值。 所以这不会编译:

List<String> lst = new ArrayList<>();
myLambda = e -> {
  lst = new ArrayList<>(); //this violates the 'final' rule
  lst.add(e);
}

然而可以调用外部变量的任何方法,即使它改变了变量的状态。这将起作用:

myLambda = e -> {
  lst.add(e);
}

即使您仍然更改了变量 lst 的状态,这也是合法代码。

但我强烈建议不要这样做。 Lambda 旨在用于函数式事务,不应更改其他地方定义的任何变量。更好的选择是在 lambda 内部创建一个列表,从 lambda 中返回它,然后将其添加到外部列表中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多