Java:如何“突变”字符串,尽管字符串是不可变的?

3
我正在开发一个API作为学生的业余项目,并使用一个URL,可以添加/减少不同的选项来更改接收到的信息。我知道字符串是不可变的,这使得事情变得有点棘手。我想出了一些混乱的方法(没有一个是强大的),来解决它,我想知道是否有一个标准的方法。我计划有单选按钮(不分配给一个按钮组;希望所有排列组合都能实现),允许我“包括”,“添加”和“排除”选项。
因此,这里是与YahooFinance API交互使用的字符串z?s=GOOG&t=7m&z=l&q=l&p=e50,m50&a=ss,sfs,vm,w14。所以,假设我有像这样的某个变量:
 String options="z?s=GOOG&t=7m&z=l&q=l&p=e50,m50&a=ss,sfs,vm,w14"

现在,考虑一下写着p=e50,m50的部分。假设我有三个单选按钮50100200,我想要勾选/取消勾选它们,从而得到一个字符串p=e50,m50,e100,m100,e200,m200,其中所有按钮都被打开,并有其他可能的组合;例如,如果100是关闭状态,那么看起来会像这样:p=e50,m50,e200,m200

有什么想法吗?我最终也想对另一个值(ss,sfs等)执行相同的操作,但让我们先从移动平均开始。


你是否考虑过使用BitArray来表示你的按钮的开/关状态?当你需要时,你可以动态构建最终的字符串。 - PM 77-1
只需构建所需的字符串。您可以简单地连接短字符串,或者使用char数组、StringBuilder或某种格式化程序进行高级操作。这并不是什么难事。 - Hot Licks
请参阅String类的规范,以了解其可用的函数。从那里开始,如果您愿意,可以转到StringBuilder。 - Hot Licks
6个回答

9

尽管其他人都是正确的,这并不是正确的方法,但这确实是他要求的方法 :) - Bill K
@BillK,我不这么认为,因为insert()需要一个偏移量,而这个答案并没有说如何获得它。此外,OP还要求删除位。所以,不,这甚至是对一个错误问题的错误答案:P - Raffaele
StringBuffer会更准确,因为它只是一个可变的字符串,但我认为这已经足够接近了。 - Bill K

6

字符串在JVM中被创建后,其内容是不可变的,这意味着没有办法改变特定实例的内容。然而这并不意味着你不能根据需要动态构造字符串。你可以使用简单的连接操作,例如:

String options="z?s=GOOG&t=7m&z=l&q=l&p=" + eOption + ",m50&a=ss,sfs,vm,w14";

从技术上讲,这创建了三个String实例,并使用StringBuffer将它们全部连接在一起。您可以自己使用StringBuffer API,调用.append()函数在希望添加选项的位置。


2
通常来说,你需要将字符串分解成各个部分,然后组装成一个新的字符串。此时,调用方可以保留原字符串和新字符串的引用,或者直接丢弃旧字符串。
以下是一个愚蠢的例子:
String hairySally = "hairy,sally";
String hairyFredSally = insertFred(hairySally);


String insertFred( String s) {
    String[] parts = s.split(",");
    return parts[0] + ",fred," + parts[1];
}

1
使用可变字符串只会导致混乱的代码。你需要一个数据结构,它易于更新参数,然后遍历该数据结构以从中创建字符串。我会将这些参数存储在一个映射中,并编写一个函数,通过迭代映射条目来从映射中创建字符串。

因此,你可以像这样在映射中存储参数:

Map<String,String> map = new LinkedHashMap<>();
map.put("s", "GOOG");
map.put("t", "7m");

并使用类似以下方式生成参数字符串:
public String createParameterString(Map<String, String> map) {
    StringBuilder builder = new StringBuilder("");
    for (Map.Entry mapEntry : map.entrySet()) {
        if (builder.length() != 0) builder.append("&");
        builder.append(mapEntry.key());
        builder.append("=")
        builder.append(mapEntry.value());
    }
    return builder.toString();
}

1
你所寻找的是格式化字符串,例如:
String querystringFormat="z?s=GOOG&t=7m&z=l&q=l&p=%s&a=ss,sfs,vm,w14"

注意,e50,m50已被替换为%s,这个格式化字符串代码表示该部分字符串将被另一个字符串替换。
然后,您可以按照通常的方式构建参数,执行:
String params = "e50,m50,e100,m100,e200,m200", 
Formatter formatter = new Formatter();
formatter.format(querystringFormat, params);
String query = formatter.toString();

使用格式化字符串还有很多其他选项和细节,但基本思想就是这样。好处在于字符串结构中不变的部分清晰明确,只需替换需要替换的部分。

它还将教你如何使用C和C++的printf,这从来不是坏事 :)


1

为什么要对字符串进行“突变”?而且为什么要从字符串的角度来解决这个问题?这个问题不是关于文本的。这个字符序列是什么意思?

?s=GOOG&t=7m&z=l&q=l&p=e50,m50&a=ss,sfs,vm,w14

这里所说的“represents”,实际上是一个映射(又称为字典),即键值对的集合,根据URI编码方案进行序列化,并附加到HTTP请求的URL中。您不希望跟踪序列化部分,特别是因为URI仅接受字符的一小部分,因此如果以字符串为基础进行推理,您可能最终得到无法工作的代码。

您需要两种方法:一种将Map序列化为URI格式,另一种从其序列化形式获取Map。请注意,Yahoo协议使用逗号将多个值分配给同一键。在序列化和反序列化时也需要考虑到这一点。

我为您写了一个要点。它没有经过彻底测试,但您可以理解思路。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接