【问题标题】:How do i write this methods with streams and lambdas?我如何用流和 lambdas 编写这个方法?
【发布时间】:2020-05-18 13:11:49
【问题描述】:

我们今天在编程课上从流和 lambda 开始,我必须做一个练习。

第一个任务是编写一个计算列表中偶数平均值的方法。我已经编写了这段代码,但显然我没有使用流。

public static double average(List<Integer> list) {

    double sum = 0;
    int i = 0;
    for (Integer integer : list) {
        if (integer % 2 == 0) {
            i++;
            sum += integer;
        }
    }
    return (sum / i);
}

编辑解决方案:

int sum = list.stream().filter(integer -> integer % 2 == 0).mapToInt(Integer::intValue).sum();
long count = list.stream().filter(integer -> integer % 2 == 0).count();

第二个任务是编写一个方法,选择所有以“a”开头(不区分大小写)或包含 3 个字符的字符串并将其更改为大写。 我的代码:

public static List<String> upperCase(List<String> list) {

    for(int i = 0; i < list.size(); i++){
        if(list.get(i).length() == 3 || Character.toString(list.get(i).charAt(0)).equalsIgnoreCase("a")){
            list.set(i, list.get(i).toUpperCase());
        }
    }
    return list;
}

编辑:解决方案:

public static List<String> upperCase(List<String> list) {


    List<String> newListOfStrings = list.stream().map(string -> string.length() == 3 ||
            Character.toString(string.charAt(0)).equalsIgnoreCase("a") ? string.toUpperCase() : string).collect(Collectors.toList());
    return newListOfStrings;

最后一项任务是返回列表,但将“g”添加到偶数,将“u”添加到奇数。 我的代码:

public static String getString(List<Integer> list){
    String s = "";
    for(Integer integer : list){
        if(integer % 2 == 0){
            s += integer.toString() + "g,";}
        else {
            s += integer.toString()+ "u,";
        }

    }
    return s.substring(0, s.length()-1);
}

编辑:解决方案:

public static String getString (List < Integer > list) {

    String result = list.stream()
            .map(integer -> integer % 2 == 0 ?
                    String.format("%d%s", integer, "g") : String.format("%d%s", integer, "u"))
            .collect(Collectors.joining(","));
    return result;

如果有人能告诉我第一个任务在流中的样子,我将不胜感激。我将自己尝试其他两个。

亲切的问候

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 我想我必须这样开始:“list.stream().forEach ...我的问题是我不知道如何在流中实现 if 条件。
  • 如果流中的条件是使用filter() 完成的。您是否阅读过文档,即Stream 的javadoc,以了解您可以使用哪些方法? --- 问题被否决,因为它“没有显示任何研究工作”(引用否决按钮的工具提示)
  • 你是对的,我没有阅读文档。这对我来说是非常压倒性的。我现在有以下代码:OptionalDouble sum = list.stream().filter(integer -&gt; integer % 2 == 0).mapToDouble(Integer::intValue).average(); 有没有更好的方法来实现它?我想摆脱 OptionalDouble 因为任务是返回正常的双精度
  • 请不要在 cmets 中添加更多信息,而是始终更新您的问题。

标签: java lambda java-stream


【解决方案1】:

第一个任务是编写一个计算列表中偶数平均值的方法。

重点是将加框的Stream&lt;Integer更改为IntStream,它提供了求和、平均、最小值、最大值等聚合操作的方法。

double average = list.stream().mapToInt(i -> i).average().getAsDouble;

请记住,如果 OptionalDouble 中没有平均值,则可能会抛出 NoSuchElementException

第二个任务是编写一个方法,选择所有以“a”开头(不区分大小写)或包含 3 个字符的字符串并将其更改为大写。

您在流末尾的forEach 方法是一个终端操作,需要Consumer,它会消耗该方法。虽然你调用了toUpperCase,但它并没有改变原来的集合并且结果被抛出(除非你打印出来)。

您想使用方法map 执行限定字符串的映射。只要您只想修改这些值并同时保留剩余的值,则不能使用filter,只要它可以修改流式传输的项目数即可。这样做:

List<String> newListOfStrings = listOfStrings.stream()
    .map(string -> string.length() == 3 || string.startsWith("a") ? 
                   string.toUpperCase() : string)
    .collect(Collectors.toList());

请注意,我使用了startsWith 更易于使用的方法。不过,您对charAt 的使用并没有错。

最后一项任务是返回列表,但将“g”添加到偶数,将“u”添加到奇数。

不是最好但相当可接受的解决方案是再次使用映射方法map,最后使用Collectors.joining(",") 将项目连接到带有分隔符的字符串。因此,您无需为, 字符而烦恼。

String result = list.stream()
    .map(integer -> integer % 2 == 0 ? integer + "g" : integer + "u")
    .collect(Collectors.joining(","));

// I find String.format better than using +
String result = list.stream()
        .map(integer -> integer % 2 == 0 ?
            String.format("%d%s", integer, "g") : String.format("%d%s", integer, "u"))
        .collect(Collectors.joining(","));

但是,如果我要实现第三个,我会使用简单的 for-each 迭代和适合字符串连接的 StringBuilder

StringBuilder sb = new StringBuilder();
for (Integer integer: list) {
    sb.append(integer);
    if (integer % 2 == 0) {
        sb.append("g,");
    } else {
        sb.append("u,");
    }
}
String result = sb.toString().substring(0, sb.length() - 1);

...或使用String.join 方法的新集合...

List<String> newList = new ArrayList<>();
for (Integer integer: list) {
    String toAdd = integer % 2 == 0 ? 
        String.format("%d%s", integer, "g") : 
        String.format("%d%s", integer, "u");
    newList.add(toAdd);
}
String result = String.join(",", newList);

【讨论】:

  • 最后一个的StringJoiner(而不是StringBuilder)怎么样?
  • @OleV.V.:我在考虑这个问题,但是自从调用 StringJoiner::add 以来,您必须在循环内(使用 String.format)连接一个整数与 "g""u"放置一个新的分隔符。你能举个例子吗?
  • 非常喜欢流媒体,我只需要list.stream().mapToInt(Integer::valueOf).mapToObj(i -&gt; i % 2 == 0 ? i + "g" : i + "u").collect(Collectors.joining(","))。随意不赞成。 :-)
  • mapToInt 不需要,你可以直接映射到字符串(输入列表是List&lt;Integer&gt;,所以:list.stream().map(i -&gt; i % 2 == 0 ? i + "g" : i + "u").collect(Collectors.joining(","))+ 处理转换。此外,我想避免在第一种情况下使用+ 进行字符串连接。我错过了什么吗?
  • 品味问题。我喜欢串联。也许如果我们更好地理解为什么 OP 想要那个输出,我们就会更好地了解它是好是坏。 PS 我不喜欢将int 放在串联的首位。我可能会做"" + i + "g" 甚至String.valueOf(i) + 'g'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多