【问题标题】:Recursively append a string to List of String in java递归地将字符串附加到java中的字符串列表
【发布时间】:2013-09-26 23:31:11
【问题描述】:

我有一个字符串列表,我想在列表中的每个字符串前面附加文本。我试图在没有 for/Iterator 循环的情况下实现这一点,比如一行代码。我找不到解决办法。

以下我尝试了一个 for 循环,但需要没有这个的解决方案。有解决办法吗?

   List<String> strings = new ArrayList<String>();
                strings.add("a");
                strings.add("b");
                strings.add("c");
            strings.add("d");

List<String> appendedList = new ArrayList<String>();
for (String s : strings) {
    appendedList.add("D" + s);
}

请帮忙。谢谢。

【问题讨论】:

  • 为什么?如果有,它的可读性会差很多。
  • 您提出的技术似乎对大多数用途都没有用。你能解释一下你为什么要这样做吗?这是作业吗?
  • 不,这不是家庭作业,但我的一位同事想知道这是否可能。类似 appendedList = StringUtils.append("x", strings)
  • 你可以通过 new ArrayList(strings) 传入列表,但是没关系..
  • 您想“在每个字符串前面附加文本”。如果您在前面添加内容,则称为 prepending

标签: java list arraylist


【解决方案1】:

如果您使用的是 Java 8,那么您可以使用新添加的 replaceAll 方法来执行此操作:

strings.replaceAll(s -> "D"+s);

这是一个完整的工作示例:

import java.util.Arrays;
import java.util.List;

public class StringTest {
  public static void main(String[] args) {
    List<String> strings = Arrays.asList("a", "b", "c", "d");
    strings.replaceAll(s -> "D"+s);
    System.out.println(strings);
  }
}

您也可以使用新的 Streams API 来执行此操作,但稍微更冗长,制作列表的副本而不是改变(更新)原始列表:

List<String> strings = Arrays.asList("a", "b", "c", "d");
strings = strings.stream()
                 .map(s -> "D"+s) // Using Lambda notation to update the entries
                 .collect(Collectors.toList());
System.out.println(strings);

请注意,我使用Arrays.asList() 来更简洁地创建列表。这不是 Java 8 中的新功能,因此您应该也可以在 Java 5/6/7 中使用它。这是我的输出:

$ java StringTest
[Da, Db, Dc, Dd]

即使您现在没有使用 Java 8,仍然需要注意这些功能已被添加,如果您在一两年内遇到类似问题,那么您可以使用新 API 中的一些东西!

【讨论】:

  • 就执行速度而言,此解决方案是否比循环更快?
  • @seinecle - 我猜它是通过某种循环在内部实现的,但它仍然会在每次迭代(lambda)中添加至少一个额外的函数调用,所以我猜它d 慢一点。但是,我不确定 Hotspot 编译器对内联 lambda 的性能有多好,所以如果这是在代码的关键区域,使用 this vs a loop 可能会编译成类似的机器代码。
【解决方案2】:

可能是这样的

public List<String> recursiveAdd(List<String> strings, List<String> finalList, String prepender){
   if(strings == null || strings.size() == 0) return finalList;
   else{
       finalList.add(prepender + strings.remove(0));
       return recursiveAdd(strings,finalList,prepender);
   }
} 

strings = recursiveAdd(strings, new ArrayList<String>(), "D");

这更像是一个函数式的解决方案,上面代码的问题是字符串会在类内部被破坏,如果你想避免这种情况,你可以在调用递归操作之前进行深层复制!

【讨论】:

  • 这是避免循环的一个很好的 CompSci 答案——用递归替换它!但是您忘记了实际转换数据。
  • 你也可以像这样在 scala 中轻松实现这个 strings.asScala.map("D"+_).asJava 你必须导入 scala.collection.JavaConverters._
【解决方案3】:

第一个想法:LINQ :)

似乎有几个 Java 的 LINQ 替代品(请参阅:Is there a Java equivalent for LINQ?What is the Java equivalent for LINQ?),您可能很幸运能找到一些有用的东西。

我将为您提供几个可能有效的示例(未经测试):

LambdaJ

使用LambdaJ的转换功能,我想这样的事情应该可以工作:

List<String> res = extract(strings, on(String.class).toString() + "D");

JPropel-Light

位于github。根据提供的示例,类似的方法也可能有效:

List<String> res = strings.select(append("D")).toList();

【讨论】:

    【解决方案4】:

    您可以使用 Google Guava 等库编写“功能样式”版本。但这通常被认为比循环更不受欢迎/清晰。

    List<String> results = Lists.transform( inputs, new Function<String,String() {
        public String apply (String input) {
            return "D"+input;
        }
    };
    

    这是为 Google Guava 编码的,但 Apache 也有一个“功能”样式库。

    实际上,这种在字符串上添加公共前缀的用例并不是很好。用户不想看到每个项目上的冗余前缀。在 UI 中,前缀应该在标题中显示一次。

    【讨论】:

      猜你喜欢
      • 2018-09-13
      • 2013-05-27
      • 2012-09-14
      • 2012-05-27
      • 2012-12-05
      • 2019-07-24
      • 2011-01-04
      • 2016-07-03
      • 2012-07-12
      相关资源
      最近更新 更多