String类型对象每个元素转换为List<Character>或List<String>

cdfive / 2024-10-10 / 原文

String str = "abc";

第一眼想到是通过String#toCharArray()转换为char[],然后再转换为List,尝试用Arrays.asList(T... a)

char[] chars = str.toCharArray();
List<char[]> list = Arrays.asList(chars);
System.out.println(list);

发现转换结果不符合预期,因为是原始类型数组,被识别为1个元素,导致转换后的list里仅1个元素,类型是char[]

用for循环来转换:

List<Character> characterList = new ArrayList<>();
for (char aChar : chars) {
    characterList.add(aChar); // 写法1
    // validList.add((Character) aChar); // 写法2
    // validList.add(Character.valueOf(aChar)); // 写法3
}

List<String> stringList = new ArrayList<>();
for (char aChar : chars) {
    stringList.add(String.valueOf(aChar));
}

这样能转换成功,但感觉写法不够简洁优雅。

经过学习和尝试,找到以下3种方法:

  1. 通过String#split("")处理后再转换
List<Character> characterList = Arrays.asList(str.split("")).stream().map(o -> o.charAt(0)).collect(Collectors.toList());
List<String> stringList = Arrays.stream(str.split("")).collect(Collectors.toList());
  1. 通过String#chars()处理后再转换
List<Character> characterList = str.chars().mapToObj(i -> (char) i).collect(Collectors.toList());
List<String> stringList = str.chars().mapToObj(i -> String.valueOf((char) i)).collect(Collectors.toList());
  1. 通过Guava提供的Chars.asList(char... backingArray)转换
List<Character> characterList = Chars.asList(str.toCharArray());
List<String> stringList = Chars.asList(str.toCharArray()).stream().map(o -> String.valueOf(o)).collect(Collectors.toList());

值得注意的是:

List<String> stringList = str.chars().mapToObj(i -> String.valueOf((char) i)).collect(Collectors.toList());

mapToObjString.valueOf前做了一个强制类型转换(char) i,否则得到的String是原字符ASCII码的整数数值。

测试代码:

List<String> tmpList1 = str.chars().mapToObj(i -> String.valueOf(i)).collect(Collectors.toList());
List<String> tmpList2 = str.chars().mapToObj(i -> String.valueOf((char) i)).collect(Collectors.toList());
// [97, 98, 99]
System.out.println(tmpList1);
// [a, b, c]
System.out.println(tmpList2);

完整demo代码如下:

import com.google.common.primitives.Chars;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author cdfive
 */
public class StringCharArrayConvertToListTest {

    public static void main(String[] args) {
        String str = "abc";

        char[] chars = str.toCharArray();
        List<char[]> invalidList = Arrays.asList(chars);
        System.out.println(invalidList);

        List<Character> validList = new ArrayList<>();
        for (char aChar : chars) {
            validList.add(aChar); // 写法1
//            validList.add((Character) aChar); // 写法2
//            validList.add(Character.valueOf(aChar)); // 写法3
        }
        System.out.println(validList);

        List<String> validStringList = new ArrayList<>();
        for (char aChar : chars) {
            validStringList.add(String.valueOf(aChar));
        }
        System.out.println(validStringList);

        System.out.println(StringUtils.center("分隔线", 50, "-"));

        List<Character> characterList1 = Arrays.asList(str.split("")).stream().map(o -> o.charAt(0)).collect(Collectors.toList());
        List<Character> characterList2 = str.chars().mapToObj(i -> (char) i).collect(Collectors.toList());
        List<Character> characterList3 = Chars.asList(str.toCharArray());
        System.out.println(characterList1);
        System.out.println(characterList2);
        System.out.println(characterList3);

        System.out.println(StringUtils.center("分隔线", 50, "-"));

        List<String> stringList1 = Arrays.stream(str.split("")).collect(Collectors.toList());
        List<String> stringList2 = str.chars().mapToObj(i -> String.valueOf((char) i)).collect(Collectors.toList());
        List<String> stringList3 = Chars.asList(str.toCharArray()).stream().map(o -> String.valueOf(o)).collect(Collectors.toList());
        System.out.println(stringList1);
        System.out.println(stringList2);
        System.out.println(stringList3);

        System.out.println(StringUtils.center("分隔线", 50, "-"));

        List<String> tmpList1 = str.chars().mapToObj(i -> String.valueOf(i)).collect(Collectors.toList());
        List<String> tmpList2 = str.chars().mapToObj(i -> String.valueOf((char) i)).collect(Collectors.toList());
        // [97, 98, 99]
        System.out.println(tmpList1);
        // [a, b, c]
        System.out.println(tmpList2);
    }
}

总结:

  • Arrays.asList(T... a)如果参数是原始类型数组,转换后的List里仅一个元素,该元素是原始数组类型

  • String的每个char元素转换为List<Character>List<Character>有多种方法,根据情况选择使用

  • String的每个char元素转换为List是为了方便对每个元素处理,如:排序、Stream流处理等

  • String#chars()里每个元素是int类型,转为String前需要强制转换为char类型,如String.valueOf((char) i)