Java 建立一个列表<;T>;一串

Java 建立一个列表<;T>;一串,java,casting,java-stream,Java,Casting,Java Stream,我试图创建一个泛型函数,该函数基于一个字符串构建任何类型的列表,该字符串包含由逗号分隔的该类型的值。我已经这样做了: public static <T> List<T> stringToList(String listStr, Class<T> itemType) { return Arrays.asList(listStr.split(",")).stream().map(x -> itemType.cast(x.replaceAll("\\s

我试图创建一个泛型函数,该函数基于一个字符串构建任何类型的列表,该字符串包含由逗号分隔的该类型的值。我已经这样做了:

public static <T> List<T> stringToList(String listStr, Class<T> itemType)
{
    return Arrays.asList(listStr.split(",")).stream().map(x -> itemType.cast(x.replaceAll("\\s+|\"|\t","")))).collect(Collectors.toList());
}
包含
x.replaceAll(“\\s+\124;\”\ t“,”)
第一个断言现在通过,第二个断言失败。控制台输出为

[Foo, Bar]
[Foo, Bar]
[1, 10, -1, 0]
[1, 10, -1, 0]
listIntegers持有Integer,因此我假设resI持有ints,或者我刚刚破坏了java的类型安全性:D

,因为问题2:一个简单的修改是传递一个
函数,而不是
。该函数将定义如何将字符串解析为所需类型的类。一些可能的值:

Function<String, String> stringParser = s -> s;
Function<String, Integer> intParser = s -> Integer.parseInt(s);
函数stringParser=s->s;
函数intParser=s->Integer.parseInt(s);
对于问题#1:在示例中,您给出的输入字符串确实包含引号。您可以使输入字符串
“Foo,Bar“
以避免在输出中使用引号。如果您无法控制输入,您可以将引号/空格等作为解析函数的一部分进行修剪,或者使用比用逗号分割更高级的方法来分隔单词-输入是CSV文件吗?

对于问题2:一个简单的修改是传递一个
函数,而不是
。函数将定义如何将字符串解析为所需类型的类。一些可能的值:

Function<String, String> stringParser = s -> s;
Function<String, Integer> intParser = s -> Integer.parseInt(s);
函数stringParser=s->s;
函数intParser=s->Integer.parseInt(s);


对于问题1:在您给出的示例中,输入字符串确实包含引号。您可以创建输入字符串
“Foo,Bar”
,以避免在输出中使用引号。如果您无法控制输入,您可以将引号/空格等作为解析功能的一部分进行修剪,或者使用比使用逗号拆分更高级的方法来分隔单词-输入是CSV文件吗?

否,您没有额外的引号。您仅有的引号是字符串中的引号。打印resS显示
resS=[“Foo”,“Bar”]
。我有。在控制台中打印字符串时,引号将被删除:List listStrings=Arrays.asList(“Foo”、“Bar”);assert(resS.containsAll(listStrings));引发异常,显示ListString包含[“Foo”、“Bar”],而resS包含[“Foo”、“Bar]”。如果您打印ListString,您将看到noquotes@chefarov如果您的定义是值是逗号分隔的,而不是别的,则引号是值的一部分。这甚至包括
“Bar”
之前的前导空格。如果您希望使用引号来允许值包含逗号,那么您需要CSV解析器,而不是普通的
split()
,因为这是CSV语法,它不仅仅是逗号分隔。@Andreas您是对的,我添加了一个正则表达式来删除不需要的字符。如果不使用Chad Dienhart的解决方案,它仍然会返回字符串列表,由于未经检查的类型转换,只是假装成一个
列表。表达式
itemType.toString().valueOf(…)
完全是胡说八道。此外,不要将答案复制到你的问题中。答案已经在那里了,没有人需要在你的问题里面有一份副本。不,你没有额外的引用。您仅有的引号是字符串中的引号。打印resS显示
resS=[“Foo”,“Bar”]
。我有。在控制台中打印字符串时,引号将被删除:List listStrings=Arrays.asList(“Foo”、“Bar”);assert(resS.containsAll(listStrings));引发异常,显示ListString包含[“Foo”、“Bar”],而resS包含[“Foo”、“Bar]”。如果您打印ListString,您将看到noquotes@chefarov如果您的定义是值是逗号分隔的,而不是别的,则引号是值的一部分。这甚至包括
“Bar”
之前的前导空格。如果您希望使用引号来允许值包含逗号,那么您需要CSV解析器,而不是普通的
split()
,因为这是CSV语法,它不仅仅是逗号分隔。@Andreas您是对的,我添加了一个正则表达式来删除不需要的字符。如果不使用Chad Dienhart的解决方案,它仍然会返回字符串列表,由于未经检查的类型转换,只是假装成一个
列表。表达式
itemType.toString().valueOf(…)
完全是胡说八道。此外,不要将答案复制到你的问题中。答案已经存在,在您的问题中没有人需要它们的副本。另外的建议:要允许对象的字符串表示包含逗号,请使用CSV解析器,而不是
split()
,因此可以使用引号来支持嵌入的逗号,首先将
字符串
转换为字符串数组,然后将
字符串
转换为特定类型。有两种不同的转换必须解决并且是必要的。另外,解决方案也不难,只需执行一个
函数。应用(x)
,然后将Lambda表达式作为调用传递,如:
stringToList(listStringsStr,(s)->{return Integer.parseInt(s);})
@chefarov您的问题是“任意类型”,那么您如何期望泛型代码知道如何从
字符串
创建我的自定义
Train
类的实例(作为示例),除非您明确允许我提供解析器,或者假设我的类有一个
String
构造函数?@guitarsteve建议回答(问题#2):显示你的建议的效果,即两个示例中
stringToList
的第二个参数是
String::toString
Integer::parseInt
,chefarov:让函数为一组预定义的类工作是可能的,但前提是什么呢?对于调用者来说,
Integer.class
并不比
Integer::valueOf
简单,从语义上讲,您在这两种情况下都传递函数,只是使用不同的形式,而
class
形式需要某种形式
Function<String, String> stringParser = s -> s;
Function<String, Integer> intParser = s -> Integer.parseInt(s);