Java 是否有一个优雅的工作来连接?

Java 是否有一个优雅的工作来连接?,java,string,concatenation,Java,String,Concatenation,我写了一个疯狂的libs程序,只是为了好玩,只是为了编写一些东西。这个程序本身非常简单,但我发现自己求助于几个串联,因为游戏的本质是将用户给定的单词放入一个句子中。是否有一种优雅的方法可以减少连接,甚至消除连接以获得更高的效率?我知道最终,如果我使用连接或不使用连接将不会有任何区别,但我很好奇是否有一种更优雅的方式来编写这个程序 更新:我使用的是java,但如果有一个通用的解决方案来避免连接,我们也会非常感激。您使用的是哪种语言 大多数高级语言将具有类似于: String.Format("{0}

我写了一个疯狂的libs程序,只是为了好玩,只是为了编写一些东西。这个程序本身非常简单,但我发现自己求助于几个串联,因为游戏的本质是将用户给定的单词放入一个句子中。是否有一种优雅的方法可以减少连接,甚至消除连接以获得更高的效率?我知道最终,如果我使用连接或不使用连接将不会有任何区别,但我很好奇是否有一种更优雅的方式来编写这个程序


更新:我使用的是java,但如果有一个通用的解决方案来避免连接,我们也会非常感激。

您使用的是哪种语言

大多数高级语言将具有类似于:

String.Format("{0} {1} {2} {3}", word1, word2, word3, word4);

你的问题有两个方面

首先,您可能希望避免在代码中直接使用串联。然后可以从运行时使用一些字符串格式化例程。这不会跳过连接,但会将它们从代码移动到运行时


其次,您可能希望更有效地进行连接。那是另一个故事。这里最重要的是为连接的字符串预先分配足够大的缓冲区,因为内存重新分配非常昂贵。将子字符串复制到结果字符串通常成本较低,这是一个必要的缺点。

通过“避免串联”,我想您的意思是为新字符串分配空间并分配它?如果你在.NET上,那么a应该会对你有所帮助。

一个解决方案可能是写出你的整个mad libs文件,并放入需要用所选单词替换的特殊标记

你刚买了一个全新的${NOUN1}, 它将带给${VERB1}您


然后,您可以使用例如:
String.replace(“${NOUN1}”,NOUN1)
替换所有单词。

就避免连接的一般方法而言,我想不出任何东西。您所能做的是为自己编写某种帮助器类,它简化了连接工作。 不过,我想给你一个建议,就是不要将字符串直接连接为

String x = "Hi";
String y = x + " there!";
在Java中,字符串连接的实现非常缓慢,因此使用StringBuffer是一种更好的做法,尤其是在执行大量连接的情况下:

StringBuffer myStringBuffer = new StringBuffer();
myStringBuffer.append("Hi");
myStringBuffer.append(" there!");

像这样的。我现在没有在编译器中检查这一点,但我相信您可以自己解决。

不确定Java,但在其他一些语言(如PHP和Javascript)中创建数组并连接其所有元素可以更快

Javascript示例:

var str = str1 + str2 + str3 + "str4" + str5 + "str6" + str7;
var str = [str1, str2, str3, "str4", str5, "str6", str7].join("");
PHP示例:

$str = $str1 . $str2 . $str3 . "str4" . $str5 . "str6" . $str7;
$str = implode("", array($str1, $str2, $str3, "str4", $str5, "str6", $str7));

如果你想在每个字符串之间加一个分隔符,这种方法是最好的。在这种情况下,它不仅更快,而且更紧凑,可读性更强。

有两种方法可以让你在游戏中完全避免连接:

  • 将故事模板存储为标记的集合:不可变部分和单词占位符。然后在集合中循环输出不可变的部分和用户单词,而不是单词占位符

  • 编写自定义打印类,该类将使用charAt循环遍历模板字符串,并输出单词而不是单词占位符


  • 与为每个单词调用String.replace或不断追加到StringBuilder不同,您可以将单词放入有序数组中,并在jdk 1.5或更高版本中使用String.format或MessageFormat.format。不幸的是,这两种模式的格式是不同的

    String myPattern = "My %s eats your %s"; // get values from the user here String result = String.format( myPattern, (Object[])myArray ); String myPattern=“我的%s吃了你的%s”; //在此处从用户获取值 String result=String.format(myPattern,(Object[])myArray); 或

    String myPattern=“我的{0}吃了你的{1}”; //在此处从用户获取值 字符串结果=MessageFormat.format(myPattern,(Object[])myArray); 下面是一个完整的程序,它用命令行中的值填充字符串

    public class Format { public static void main( String[] args ) { String pattern = "My %s eats your %s"; System.out.println( String.format( pattern, (Object[])args )); } } 公共类格式 { 公共静态void main(字符串[]args) { String pattern=“我的%s吃了你的%s”; System.out.println(String.format(pattern,(Object[])args)); } }
    如果您有一个字符串,需要经常修改它,那么使用char[]数组并在修改完后创建一个字符串就可以了。

    如果您想这样做,当然可以不用连接。虽然这可能不太值得

    这在一定程度上取决于将在何处显示结果。如果是在web或控制台上,则可以将结果直接写入输出流

    例如,如果您的模板类似于“从%002跳出的%001”,您可以:

    1) 扫描字符串以查找变量的位置。 2) 在本例中,将字符串拆分为组件列表“the”,“hopped out the” 3) 循环浏览列表中的元素和结果,并将它们转储到输出,如下所示:

    PrintStream  = //get output from somewhere
    for(int i = 0; i < pieces.size()-1 ; i++){
       ps.print(peices.get(i));
       ps.print(answers.get(i));
    }
    ps.print(pieces.get(pieces.size()-1));//last one
    
    PrintStream=//从某处获取输出
    对于(int i=0;i
    现在。我不知道你是否会称之为“优雅”。可能会有点快。就像我说的,如果这是一个web服务,并且它变得非常流行,那么可能是合适的,等等

    如果这是一个GUI应用程序,您可以编写代码分别绘制字符串,但这可能需要比串联更多的时间


    但您可以做的一件事是使用ByteArrayOutputStream并预先分配足够的空间,以便它可以包含已填充的madlib,而无需进行额外分配。那也很快

    如果为了保持整洁,你为什么要避免连接呢?试着把它很好地排列起来,结果可能会出人意料地好。即使你担心性能,你也可能不需要使用字符串生成器,我相信如果你简单地进行一系列连接(即“fdsfsd”+var1+var2+dsfsdf)
    PrintStream  = //get output from somewhere
    for(int i = 0; i < pieces.size()-1 ; i++){
       ps.print(peices.get(i));
       ps.print(answers.get(i));
    }
    ps.print(pieces.get(pieces.size()-1));//last one