convert comma separated string to list without intermediate container

前端 未结 7 2026
误落风尘
误落风尘 2021-01-01 12:36

I need to convert comma separated string to list of integers. For example if I have following string

String numbersArray = \"1, 2, 3, 5, 7, 9,\";


        
相关标签:
7条回答
  • 2021-01-01 13:02

    This works, as long as the String ends in a comma, like your example.

     String numbersArray = "1, 2, 3, 14, 5,";
     List<Integer> list = new ArrayList<Integer>();
     for (int i = 0, j, n = numbersArray.length(); i < n; i = j + 1) {
         j = numbersArray.indexOf(",", i);
         list.add(Integer.parseInt(numbersArray.substring(i, j).trim()));
     }
    

    However, it's pretty useless, as on my machine it's about 2 times slower than the original.

    This next solution, on the other hand, is surprisingly fast. I tested it on lists of 50000 integers obtained using Math.abs(random.nextInt()) and it was about 4 times faster than the original.

    List<Integer> list = new ArrayList<Integer>();
    for (int i = 0, a = 0, n = numbersArray.length(); i < n; i++) {
        char c = numbersArray.charAt(i);
        if (c == ',') {
            list.add(a);
            a = 0;
        } else if (c != ' ') {
            a = a * 10 + (c - '0');
        }
    }
    

    And this is about twice as fast again:

    List<Integer> list = new ArrayList<Integer>();
    for (int i = 0, a = 0, n = numbersArray.length(); i < n; i++) {
        switch(numbersArray.charAt(i)) {
            case ',': list.add(a); a = 0; break;
            case ' ': break;
            case '0': a = a * 10; break;
            case '1': a = a * 10 + 1; break;
            case '2': a = a * 10 + 2; break;
            case '3': a = a * 10 + 3; break;
            case '4': a = a * 10 + 4; break;
            case '5': a = a * 10 + 5; break;
            case '6': a = a * 10 + 6; break;
            case '7': a = a * 10 + 7; break;
            case '8': a = a * 10 + 8; break;
            case '9': a = a * 10 + 9; break;
            default: throw new AssertionError();
        }
    }
    
    0 讨论(0)
  • 2021-01-01 13:04

    I really like @MarounMaroun's answer but I wonder if it is even better to use the Arrays.stream-method instead of Arrays.asList.

    int[] numbers = Arrays.stream(numbersArray.split(","))
                    .map(String::trim).mapToInt(Integer::parseInt).toArray();
    

    This SO-question discusses this further and summarizes it as such:

    because you leave the conversion of the array to a stream to the JDK - let it be responsible for efficiency etc.

    0 讨论(0)
  • 2021-01-01 13:19

    If you're using Java 8, you can:

    int[] numbers = Arrays.asList(numbersArray.split(",")).stream()
      .map(String::trim)
      .mapToInt(Integer::parseInt).toArray();
    

    If not, I think your approach is the best option available.

    0 讨论(0)
  • 2021-01-01 13:23

    Using java 8 Streams:

    List<Integer> longIds = Stream.of(commaSeperatedString.split(","))
                    .map(Integer::parseInt)
                    .collect(Collectors.toList());
    
    0 讨论(0)
  • 2021-01-01 13:23

    If you are willing to use Google Guava ( https://code.google.com/p/guava-libraries/ ) , splitter is your friend

        List<Integer> list = new ArrayList<Integer>();
        for ( String s : Splitter.on(',').trimResults().omitEmptyStrings().split("1, 2, 3, 14, 5,") ) {
          list.add(Integer.parseInt(s)); 
        }
    

    or, you could use something similar to your original approach and:

    List<Integer> list = new ArrayList<Integer>();
    for (String s :"1, 2, 3, 5, 7, 9,".split(",") ) {
        list.add(Integer.parseInt(s.trim()));
    }
    
    0 讨论(0)
  • 2021-01-01 13:23

    I think below piece of code could be helpful for you.

    import java.util.Scanner;
    
    public class Solution {
        public static void main(String[] args) throws java.io.IOException {
            String numbersArray = "1, 2, 3, 5, 7, 9,";
            System.out.println(numbersArray);
            Scanner sc = new Scanner(numbersArray);
            sc.useDelimiter("(, *)*");
            try{
                while(true){
                    System.out.println(sc.nextInt());
                }
            } catch (Exception e) {
                System.out.println("reading is completed");
            }
        }
    }
    

    Instead of using System.out.println add it to the Integer list.

    Here we are not traversing through the complete list multiple times, instead we traverse only once and storing them in array.

    0 讨论(0)
提交回复
热议问题