Returns a string containing the string representation of each of {@code parts}, using the previously configured separator between each.
(Iterable<?> parts)
| 191 | * previously configured separator between each. |
| 192 | */ |
| 193 | public String join(Iterable<?> parts) { |
| 194 | /* |
| 195 | * If we can quickly determine how many elements there are likely to be, then we can use the |
| 196 | * fastest possible implementation, which delegates to the array overload of String.join. |
| 197 | * |
| 198 | * In theory, we can quickly determine the size of any Collection. However, thanks to |
| 199 | * regrettable implementations like our own Sets.filter, Collection.size() is sometimes a |
| 200 | * linear-time operation, and it can even have side effects. Thus, we limit the special case to |
| 201 | * List, which is _even more likely_ to have size() implemented to be fast and side-effect-free. |
| 202 | * |
| 203 | * We could consider recognizing specific other collections as safe (like ImmutableCollection, |
| 204 | * except ContiguousSet!) or as not worth this optimization (CopyOnWriteArrayList?). |
| 205 | */ |
| 206 | if (parts instanceof List) { |
| 207 | int size = ((List<?>) parts).size(); |
| 208 | if (size == 0) { |
| 209 | return ""; |
| 210 | } |
| 211 | CharSequence[] toJoin = new CharSequence[size]; |
| 212 | int i = 0; |
| 213 | for (Object part : parts) { |
| 214 | if (i == toJoin.length) { |
| 215 | /* |
| 216 | * We first initialized toJoin to the size of the input collection. However, that size can |
| 217 | * go out of date (for a collection like CopyOnWriteArrayList, which may have been safely |
| 218 | * modified concurrently), or it might have been only an estimate to begin with (for a |
| 219 | * collection like ConcurrentHashMap, which sums up several counters that may not be in |
| 220 | * sync with one another). We accommodate that by resizing as necessary. |
| 221 | */ |
| 222 | toJoin = Arrays.copyOf(toJoin, expandedCapacity(toJoin.length, toJoin.length + 1)); |
| 223 | } |
| 224 | toJoin[i++] = toString(part); |
| 225 | } |
| 226 | // We might not have seen the expected number of elements, as discussed above. |
| 227 | if (i != toJoin.length) { |
| 228 | toJoin = Arrays.copyOf(toJoin, i); |
| 229 | } |
| 230 | return String.join(separator, toJoin); |
| 231 | } |
| 232 | return join(parts.iterator()); |
| 233 | } |
| 234 | |
| 235 | /* |
| 236 | * TODO: b/381289911 - Make the Iterator overload use StringJoiner (including Android or not)—or |
no test coverage detected