google / guava

Google core libraries for Java
Apache License 2.0
50.12k stars 10.89k forks source link

Improve Splitter.fixedLength() javadocs when splitter.limit() is used #3321

Closed BrettGoreham closed 5 years ago

BrettGoreham commented 5 years ago

Example. Splitter.fixedLength(35).limit(6).splitToList(stringToSplit)

This will result in 6 strings being made in the list. as expected. however the first 5 will have the correct fixed length of 35, while the last string will be the rest of the string that is left after 5 * 35 characters.

If we are to expect fixed length strings after using Fixed length, shouldn't all of the returned strings be of that length.

Current work around would be to use substring to ensure that the string isnt longer than limit * fixedLength.

a use case example is SWIFT banking format messages. Where fields have a specific amount of lines and characters per line. Example of such a field is found in Swift documentation here: https://www2.swift.com/knowledgecentre/publications/usgf_20180720/3.0?topic=mt103-18-field-70.htm

Being able to split a string into exactly what we need here would be useful.

kluever commented 5 years ago

Hmm, that behavior does seem surprising. We even have tests that verify it though:

  public void testLimitOne() {
    String simple = "abcd";
    Iterable<String> letters = Splitter.fixedLength(1).limit(1).split(simple);
    assertThat(letters).containsExactly("abcd").inOrder();
  }

  public void testLimitFixedLength() {
    String simple = "abcd";
    Iterable<String> letters = Splitter.fixedLength(1).limit(2).split(simple);
    assertThat(letters).containsExactly("a", "bcd").inOrder();
  }
BrettGoreham commented 5 years ago

Thanks for your quick response!

Yeah i would expect the last element to have at most the fixed length because from the fixed length documentation it says: "The last piece can be smaller than {@code length} but will never be empty". but has nothing about it maybe being bigger!

If this is expected behavior though you can close this issue. :) But I wouldn't mind maybe having a flag or something to trim the last result as well, however I'm not sure How feasible this would be or if it makes sense API wise.

kluever commented 5 years ago

OK I guess the important piece of javadocs is that Splitter.limit(int) says that it "stops splitting after it reaches the limit".

So Splitter.fixedLength(35).limit(6).splitToList(stringToSplit) will peal off 5x 35-length chunks, and then stop splitting (thus returning the 6th chunk as the rest of the string).

That being said, I think there's room to improve the javadocs here.

kluever commented 5 years ago

OK, I've added a blurb about this (it should be mirrored out shortly). Thanks again for filing it...it definitely caught me by surprise as well!

BrettGoreham commented 5 years ago

No problem happy to help, Ill have to move away from the library in this case.

And roll my own solution :)

Thanks for the help!

Den ons. 21. nov. 2018, 16.57 skrev Kurt Alfred Kluever < notifications@github.com:

OK, I've added a blurb about this (it should be mirrored out shortly). Thanks again for filing it...it definitely caught me by surprise as well!

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/google/guava/issues/3321#issuecomment-440716540, or mute the thread https://github.com/notifications/unsubscribe-auth/AJpCUDl5pM10XOgLRXaL9QIcBWyVvSqUks5uxXfXgaJpZM4Ys8e1 .

nick-someone commented 5 years ago

FWIW, you can use:

List<String> records = Splitter.fixedLength(35).limit(6+1).splitToList(string);
if (records.size() > 6) {  // If there are more than 35*6 characters in the string, only see the first 35*6
  records = records.subList(0,6);
}

Which may be a bit annoying, but is hopefully easier than rewriting everything ;)