Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 你会怎么写一个“你会怎么写?”;纯粹的;从列表中删除元素的函数?_Java_Functional Programming_Pure Function - Fatal编程技术网

Java 你会怎么写一个“你会怎么写?”;纯粹的;从列表中删除元素的函数?

Java 你会怎么写一个“你会怎么写?”;纯粹的;从列表中删除元素的函数?,java,functional-programming,pure-function,Java,Functional Programming,Pure Function,在Java(或任何类似语言)中,如何编写从列表中删除元素的(或方法) 如果元素在列表中,我们只需返回一个新的(理想情况下是不可变的)列表,其中包含输入列表中的所有元素,减去我们删除的元素 但是,如果在列表中找不到元素,您将如何处理这种情况 假设该方法接收到两个参数,列表和要删除的元素: public SOMETHING remove(final List<String> list, final String element){ // Copy the input list a

在Java(或任何类似语言)中,如何编写从列表中删除元素的(或方法)

如果元素在列表中,我们只需返回一个新的(理想情况下是不可变的)列表,其中包含输入列表中的所有元素,减去我们删除的元素

但是,如果在列表中找不到元素,您将如何处理这种情况

假设该方法接收到两个参数,
列表
和要删除的
元素

public SOMETHING remove(final List<String> list, final String element){
    // Copy the input list and remove the first occurrence of 'element', if I find it.
    // 
    // if I don't find it ... do something clever here ...
}
public SOMETHING remove(最终列表,最终字符串元素){
//复制输入列表并删除“element”的第一个匹配项(如果我找到的话)。
// 
//如果我找不到它…在这里做点聪明的事。。。
}
如果调用此方法,并且
元素
不包含在
列表中

  • 抛出异常可能会使方法“不纯”(?)
  • 修改输入列表并返回布尔值(类似于)可能会使方法“不纯”(修改输入会产生副作用)
  • 如果调用此方法,将输入返回为输出对我来说似乎是不直观的
  • 返回一个
    可选的.of(listCopy)
    (编辑:发布后添加到我的问题中)
  • 还有其他想法吗
编辑 我应该提到,我只想删除第一次出现的
元素
,因此如果输入
列表
中有多次出现的
元素
,我不想通过调用remove()方法(例如使用
流().filter()
)将它们全部删除。我刚刚编辑了代码示例中的注释以反映这一点。然而,这与我的问题并不完全相关,因为我的主要问题围绕着如何使方法直观地使用并保持“纯粹”

编辑2
我在上述建议的基础上又增加了一个想法。返回
Optional.of(listCopy)
似乎是迄今为止提出的解决方案中最优雅的解决方案。它强制调用方检查请求的操作是否成功,并且(如果成功),它返回一个新列表,从而不修改原始输入列表。如果操作未成功(
元素
未在
列表
中找到),则该方法返回
Optional.empty()
。在我看来,这也将满足以下提到的参考完整性

您可以构建一个新的
列表
并循环输入数组,添加每个不是
元素的元素
,然后返回新列表

如何:

public List<String> remove(final List<String> list, final String element) {
    List<String> result = new ArrayList<String>(list);
    result.remove(element);
    return result;
}
公共列表删除(最终列表,最终字符串元素){
列表结果=新的ArrayList(列表);
结果:移除(元素);
返回结果;
}
从维基百科,它必须:

  • 对于相同的输入有相同的返回-看不出任何原因为什么这里不正确,没有随机,没有IO,等等
  • 无状态-此函数只处理参数。也可以使其
    静态
编辑(只看到关于每次返回新列表的注释)

如果您试图用Java实现函数式代码,那么它是一个新列表这一事实会导致问题。您可能引用了一个名为引用透明度的属性。总之,如果一个值可以替换为对其自身的引用,则该值具有引用透明性,反之亦然,而不改变程序的语义。Java并不真正支持这一点,这也是Java不能真正发挥功能的原因之一

在Haskell中,(几乎)所有表达式都具有引用透明性,即一个列表
[1,2,3,4]
不仅仅等同于另一个列表
[1,2,3,4]
,它是相同的东西。这类似于在数学中,
7
7
是一样的,说“那
7
与我在这个等式中的
7
不一样”是没有意义的

回到Java,您需要后续调用返回相同的输出。因此,由你来定义“相同”的含义。在函数世界中,这通常由值决定(即使用
数组.equals()
)。但是,如果您想使用
==
(即,当且仅当两个列表在内存中占据相同位置时,它们才相等),那么功能样式可能不是您想要的


希望这能澄清问题。

对现有列表的任何变异都会导致维基百科的“属性1”失败

它的计算没有副作用(局部静态变量、非局部变量、可变引用参数或I/O流没有突变)

在这里,您唯一真正的希望是返回一个新的
列表
,其中包含复制的所有元素,但要删除的元素除外

public List<String> remove(final List<String> list, final String element) {
    return list.stream()
                   .filter(e -> !Objects.equals(e, element))
                   .collect(Collectors.toList());
}
公共列表删除(最终列表,最终字符串元素){
return list.stream()
.filter(e->!Objects.equals(e,element))
.collect(Collectors.toList());
}
这也会处理“元素不在列表中”的场景,因为您会返回一个新的列表实例,其中的元素与旧的列表实例相同。实际上,如果数据的状态没有改变,那么返回相同的状态就没有什么实际的危害

但是请记住,这实际上是非常昂贵和/或浪费的,对于收藏来说并不是一个有价值的练习。

例如,使用:

ListIterator iter=books.ListIterator();
while(iter.hasNext()){
if(iter.next().getIsbn().equals(isbn)){
iter.remove();
}
}

浏览您提到的要点:

  • 抛出异常可能会使方法“不纯”(?)
    • 如果要返回相同的列表或引发异常,这是一个实现决策。至于“纯函数”-只要你是一致的,相同的输入产生相同的结果(或
      ListIterator<Book> iter = books.listIterator();
      while(iter.hasNext()){
          if(iter.next().getIsbn().equals(isbn)){
              iter.remove();
          }
      }
      
      return list.stream()
       .filter(e -> !e.equals(element))
       .collect(Collectors.toList());