Java 你会怎么写一个“你会怎么写?”;纯粹的;从列表中删除元素的函数?
在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
列表
和要删除的元素
:
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,等等
- 无状态-此函数只处理参数。也可以使其
静态
[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());