14

I have a toString() representation of an ArrayList.

Copying the toString() value to clipboard, I want to copy it back into my IDE editor, and create the ArrayList instance in one line. In fact, what I'm really doing is this:

  • my ArrayList.toString() has data I need to setup a unit test.
  • I want to copy this ArrayList.toString() into my editor to build a test against this edge case
  • I don't want to parse anything by hand

My input looks like this:

[15.82, 15.870000000000001, 15.92, 16.32, 16.32, 16.32, 16.32, 17.05, 17.05, 17.05, 17.05, 18.29, 18.29, 19.16]

The following do not work:

  • Arrays.asList()
  • google collections Lists.newArrayList()

Suggestions?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
dotnetnewbie
  • 151
  • 1
  • 1
  • 4
  • 2
    Can you detail why Arrays.asList(15.82, 15.870000000000001, 15.92, 16.32, 16.32, 16.32, 16.32, 17.05, 17.05, 17.05, 17.05, 18.29, 18.29, 19.16) was not able to provide you a correct list ? – Riduidel May 05 '10 at 14:37
  • i picked that one arbitrarily. sorry you are right about this. my testcase list was of strings: "[x,y,z]" – dotnetnewbie May 05 '10 at 15:04

6 Answers6

25

Substring the braces away, split it on , (comma and space) and finally feed it to Arrays#asList().

 String s = "[15.82, 15.870000000000001, 15.92, 16.32, 16.32, 16.32, 16.32, 17.05, 17.05, 17.05, 17.05, 18.29, 18.29, 19.16]";
 List<String> list = Arrays.asList(s.substring(1, s.length() - 1).split(", "));

Note that this will work in your particular case, but not in all circumstances. You may for example have a list of strings of which at least one contains a subsequent comma and space. The split would then fail.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 2
    I think you want s.length()-1, as the character at the endIndex is not included in the substring – Ophidian May 05 '10 at 14:52
  • just a matter of personal preference, but I prefer not to parse and like the google splitter solution better. – dotnetnewbie May 05 '10 at 15:07
  • Your choice. I just wanted to prove that it *works*. You namely mentioned that it "do not work". Since you already gave the answer using Google Collections yourself beforehand, I did not want to waste time to duplicate it. – BalusC May 05 '10 at 15:23
  • thanks. just to clarify - i was looking for the path of least resistance / fastest way as i just needed data for a unit test. i agree w/ parsing i could have done it...but i really wanted how can i copy ArrayList.toString() straight into my test case and have it work w/ no additional mod's. i added my google coll solution as i came up w/ it a minute after posting. thx again – dotnetnewbie May 05 '10 at 16:06
  • Thanx BalusC . It helped very much. –  Feb 04 '16 at 17:47
3

Generally speaking the toString() of any objects does not contain information to reproduce the original object without any further information.

In your specific case the example could be produced by many different ArrayList instances (as well as pretty much all other List implementations which have identical toString()) implementations.

As an extreme example, think of an ArrayList that contains a single element which is the String with the content 15.82, 15.870000000000001, 15.92, 16.32, 16.32, 16.32, 16.32, 17.05, 17.05, 17.05, 17.05, 18.29, 18.29, 19.16. That ArrayList would produce the exact same output as your original ArrayList. And since two different inputs produce the same output, there's no way this function can be reversed without additional information.

If, however, we have additional information, such as the content type of the original ArrayList, then it becomes possible in some cases. If we know that all elements of the List were of type Double, then it's actually pretty easy:

public static List<Double> stringToList(final String input) {
    String[] elements = input.substring(1, input.length() - 1).split(", ");
    List<Double> result = new ArrayList<Double>(elements.length);
    for (String item : elements) {
        result.add(Double.valueOf(item));
    }
    return result;
}

Granted, it's not a one-liner, but it's not too bad.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
1

this works, but perhaps someone has something more elegant?

    List<String> list = Lists.newArrayList(Splitter.on(",").omitEmptyStrings().split("JUN10, SEP10, DEC10, MAR11, JUN11, SEP11, DEC11, MAR12, JUN12, SEP12, DEC12, MAR13, DEC13, DEC14"));
    assertEquals(14, list.size());
dotnetnewbie
  • 151
  • 1
  • 1
  • 4
0

I want to copy this ArrayList.toString() into my editor to build a test against this edge case

If at all you are copying, can't you just copy values omitting the square brackets and call an

Arrays.asList(...) ?
ring bearer
  • 20,383
  • 7
  • 59
  • 72
  • yep - i amended. sorry. values of type Number work fine; but what about when your list has string elements? – dotnetnewbie May 05 '10 at 15:06
  • @dotnetnewbie: String elements will ony ever work if none of the String elements contains the substring `", "`. – Joachim Sauer May 05 '10 at 15:11
  • the point of he exercise is to copy and paste into unit test and get unit test working w/ least path of resistance assuming you have a ArrayList.toString() that you can copy to clipboard from IDE – dotnetnewbie May 05 '10 at 16:12
0

If you are just looking for a copy paste solution,

    Arrays.asList(15.82, 15.870000000000001, 15.92, 16.32, 16.32, 16.32, 16.32, 17.05, 17.05, 17.05, 17.05, 18.29, 18.29, 19.16);

i.e. delete the quotes and square brackets before trying to put it into asList(). That should give you a List which you could easily use to create a new ArrayList.

If the data are more complicated than doubles, you may have to find a way to parse them.

ILMTitan
  • 10,751
  • 3
  • 30
  • 46
0

The "must be one line" requirement pretty much ensures that you're going to get some ugly mess of chained API calls unless you write a helper method to encapsulate things.

It's kind of ugly, but similar to dotnetnewbie's approach:

List<String> result = Arrays.asList(listString.substring(1, listString.length()-1).split(",\\s*"));

It's off the cuff so I'm sure that can be cleaned up a fair bit.

A more elegant and easier to read approach would definitely be to either break it out over a couple of lines or refactor to a helper method in your test case (or a Util class) that you can call with your string and have it return the output that you'd like.

Ophidian
  • 9,775
  • 2
  • 29
  • 27