【问题标题】:Interface as argument, returning result接口作为参数,返回结果
【发布时间】:2020-04-22 15:18:51
【问题描述】:

我正在做以下编程练习:Moves in squared strings (I)。声明是:

给定一个 n 行字符串,每个子字符串为 n 个字符 长:例如:

s = "abcd\nefgh\nijkl\nmnop"

我们将研究这个正方形字符串的一些变换。

Vertical mirror: vert_mirror (or vertMirror or vert-mirror)

vert_mirror(s) => "dcba\nhgfe\nlkji\nponm"

Horizontal mirror: hor_mirror (or horMirror or hor-mirror)

hor_mirror(s) => "mnop\nijkl\nefgh\nabcd"

或打印:

垂直镜像|水平镜像abcd --> dcba |abcd --> mnop efgh hgfe |efgh ijkl ijkl lkji |ijkl
efgh mnop ponm |mnop abcd

任务:

Write these two functions

high-order function oper(fct, s) where
    fct is the function of one variable f to apply to the string s (fct will be one of vertMirror, horMirror)

示例:

s = "abcd\nefgh\nijkl\nmnop" 操作(vert_mirror, s) => “dcba\nhgfe\nlkji\nponm”操作(hor_mirror,s)=> "mnop\nijkl\nefgh\nabcd"

我需要一些帮助,因为这是我第一次需要将函数作为方法的参数传递。最初的测试用例是(取自练习):

import static org.junit.Assert.*;
import org.junit.Test;

public class OpstringsTest {

    private static void testing(String actual, String expected) {
        assertEquals(expected, actual);
    }
    @Test
    public void test() {
        System.out.println("Fixed Tests vertMirror");
        String s = "hSgdHQ\nHnDMao\nClNNxX\niRvxxH\nbqTVvA\nwvSyRu";
        String r = "QHdgSh\noaMDnH\nXxNNlC\nHxxvRi\nAvVTqb\nuRySvw";
        testing(Opstrings.oper(Opstrings::vertMirror, s), r);
        s = "IzOTWE\nkkbeCM\nWuzZxM\nvDddJw\njiJyHF\nPVHfSx";
        r = "EWTOzI\nMCebkk\nMxZzuW\nwJddDv\nFHyJij\nxSfHVP";
        testing(Opstrings.oper(Opstrings::vertMirror, s), r);

        System.out.println("Fixed Tests horMirror");
        s = "lVHt\nJVhv\nCSbg\nyeCt";
        r = "yeCt\nCSbg\nJVhv\nlVHt";        
        testing(Opstrings.oper(Opstrings::horMirror, s), r);
        s = "njMK\ndbrZ\nLPKo\ncEYz";
        r = "cEYz\nLPKo\ndbrZ\nnjMK";
        testing(Opstrings.oper(Opstrings::horMirror, s), r);
    }
}

我尝试了以下实现:

import java.util.function.*;
class Opstrings {    
  public static String vertMirror (String string) {
    String[] words = string.split("\\s+");
    StringBuilder sb = new StringBuilder();
    for(String word : words){
      sb.append(new StringBuilder(word).reverse()+"\n");
    }
    return string.strip().toString();
  }
  public static String horMirror (String string) {
    return new StringBuilder(string).reverse().toString();
  }
  public static String oper/*????️*/(Consumer<String> operator, String s) {
    return operator.accept(s);
  }
}

而当我们执行前面的代码时,编译器会输出:

./src/main/java/Opstrings.java:15:错误:不兼容的类型:void 无法转换为字符串 返回 operator.accept(s); ^ 1 个错误

我了解 Consumer 被定义为返回 void。所以然后我决定进行调查,我读到 Callable 能够返回结果。于是我尝试了:

import java.util.concurrent.Callable;
class Opstrings {    
  public static String vertMirror (String string) {
    String[] words = string.split("\\s+");
    StringBuilder sb = new StringBuilder();
    for(String word : words){
      sb.append(new StringBuilder(word).reverse()+"\n");
    }
    return string.strip().toString();
  }
  public static String horMirror (String string) {
    return new StringBuilder(string).reverse().toString();
  }
  public static String oper/*????️*/(Callable operator, String s) {
    return operator.accept(s);
  }
}

但是这次我们的编译器说我们不能在需要 String 时调用没有参数的函数(来自测试用例):

./src/test/java/OpstringsTest.java:14:错误:不兼容的类型: 无效的方法引用 测试(Opstrings.oper(Opstrings::vertMirror, s), r); ^ 类 Opstrings 中的方法 vertMirror 不能应用于给定类型 必需:字符串 发现:没有参数 原因:实际参数列表和形式参数列表的长度不同。/src/test/java/OpstringsTest.java:17:错误:不兼容的类型: 无效的方法引用

另外,我也看过:

您能帮我弄清楚我们如何将函数式接口作为方法的参数传递并返回其结果吗?

编辑:正如@JB Nizet 所说,它可以使用 UnaryOperator 来完成:

import java.util.function.*;

class Opstrings {    
  public static String vertMirror (String string) {
    String[] words = string.split("\\s+");
    for(int i = 0; i < words.length; i++){
      words[i] = new StringBuilder(words[i]).reverse().toString();
    }
    return String.join("\n",words);
  }

  public static String horMirror (String string) {
    String[] words = string.split("\\s+");
    StringBuilder sb = new StringBuilder();
    for(int i = words.length-1; i >= 0; i--){
      sb.append(words[i]+"\n");
    }
    return sb.toString().strip();
  }

  public static String oper/*????️*/(UnaryOperator<String> operator, String s) {
    return operator.apply(s);
  }
}

【问题讨论】:

    标签: java function methods lambda java-8


    【解决方案1】:

    Consumer 是一个从有到无的函数(void)。 Callable 是一个从无到有的函数。你想要一个从某物到另一物的功能。

    这就是Function 的用途。或者,由于在您的情况下返回类型和参数类型相同,UnaryOperator

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      • 1970-01-01
      • 2017-01-25
      • 1970-01-01
      相关资源
      最近更新 更多