2016-01-27 2 views
2

Я пытаюсь создать общую функцию, которая строит список любого типа на основе строки, которая содержит значения этого типа, разделенные запятой. Я сделал это:Создайте список <T> из строки

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()); 
} 

Когда я пытаюсь проверить его:

String listStringsStr = "\"Foo\", \"Bar\""; 
List<String> resS = stringToList(listStringsStr, String.class); 

String listIntegersStr = "1,10,-1,0"; 
List<Integer> resI = stringToList(listStringsStr, Integer.class); 

У меня есть две проблемы.

  1. В первом случае (String) я получаю дополнительную двойную кавычку вокруг каждой строки: "" Foo "", "Bar".
  2. Во втором случае (целое число) я получаю java.lang.ClassCastException: Cannot cast java.lang.String to java.lang.Integer, что означает, что он не может преобразовать «1» в 1. Я знаю, что это работает с Integer::parseInt, но я хочу сделать общий метод.

Любые идеи?

[EDIT] - Потому что я вызвал замешательство, как я отправил это, я добавляю тестовый код:

String listStringsStr = "\"Foo\", \"Bar\""; 
List<String> listStrings = Arrays.asList("Foo", "Bar"); 
String listIntegersStr = "1,10,-1,0"; 
List<Integer> listIntegers = Arrays.asList(1, 10, -1, 0); 

List<String> resS = stringToList(listStringsStr, String.class); 
System.out.println(resS); 
System.out.println(listStrings); 
assert (resS.containsAll(listStrings)); 

List<Integer> resI = stringToList(listIntegersStr, Integer.class); 
System.out.println(resI); 
System.out.println(listIntegers); 
assert (resI.containsAll(listIntegers)); 

После включения x.replaceAll("\\s+|\"|\t","") первое утверждение теперь пройти, второй не может. Выход консоли

[Foo, Bar] 
[Foo, Bar] 
[1, 10, -1, 0] 
[1, 10, -1, 0] 

listIntegers держит Integer, таким образом, я полагаю, RESI держит Интс, или я просто сломал типобезопасность в Java: D

+0

Нет, у вас нет дополнительных кавычек. Единственные кавычки, которые у вас есть, это те, которые находятся в строке. Печать resS показывает 'resS = [" Foo "," Bar "]'. –

+0

У меня есть. Когда вы печатаете строку в консоли, кавычки удаляются: Список listStrings = Arrays.asList («Foo», «Bar»); assert (resS.containsAll (listStrings)); вызывает исключение, показывающее, что listStrings содержат ["Foo", "Bar"], где resS содержит ["" Foo "", "Bar" "]. Если вы печатаете listStrings, вы не увидите никаких котировок – chefarov

+0

@chefarov Если ваше определение таково, что значения разделены запятой и ничего больше, то кавычки являются * частью * значения. Это даже включает в себя ведущее пространство перед «Бар». Если вы хотите использовать кавычки для того, чтобы значение содержало запятые, вам нужен CSV Parser, а не простой 'split()', поскольку это синтаксис CSV, который больше, чем просто разделение запятой. – Andreas

ответ

6

Для задачи № 2: Простая модификация будет проходить Function<String, T> вместо Class<T>. Функция будет определять, как разбирать строку как класс требуемого типа. Возможные значения:

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

Для задачи № 1: В примере, вы дали входные строки сделать содержат кавычки. Вы могли бы сделать строку ввода "Foo,Bar", чтобы избежать кавычек на выходе. Если у вас нет контроля над входом, вы можете обрезать кавычки/пробелы/etc. как часть функции синтаксического анализа, или отделить слова чем-то более продвинутым, чем разделение запятыми - является ли вход CSV-файла?

+1

Дополнительное предложение: Чтобы разрешить строковое представление объекта включать запятую, используйте синтаксический анализатор CSV вместо 'split()', поэтому цитирование может использоваться для поддержки встроенных запятых. – Andreas

+0

Должно быть более простое решение, чем передача функции преобразования в качестве аргумента в другую функцию преобразования. По крайней мере, на любом другом языке, который я знаю – chefarov

+0

Ну, это зависит от содержимого вашей входной строки. Очевидно, что он может содержать строки. Как насчет чисел, списков, карт или более сложных объектов? Являются ли они строками из файла CSV? – guitarsteve