Java: преобразование списка в строку
в JavaScript Array.join()
js>["Bill","Bob","Steve"].join(" and ")
Bill and Bob and Steve
есть ли в Java что-нибудь подобное? Я знаю, что могу что-то придумать сам с StringBuilder:
static public String join(List<String> list, String conjunction)
{
StringBuilder sb = new StringBuilder();
boolean first = true;
for (String item : list)
{
if (first)
first = false;
else
sb.append(conjunction);
sb.append(item);
}
return sb.toString();
}
...но нет смысла делать это, если что-то вроде этого уже является частью JDK.
22 ответов:
С Java 8, вы можете сделать это без каких-либо сторонней библиотеки.
Если вы хотите присоединиться к коллекции строк, вы можете использовать новый строку.присоединяйтесь() способ:
List<String> list = Arrays.asList("foo", "bar", "baz"); String joined = String.join(" and ", list); // "foo and bar and baz"Если у вас есть коллекция с другим типом, чем String, вы можете использовать Stream API с соединять коллектор:
List<Person> list = Arrays.asList( new Person("John", "Smith"), new Person("Anna", "Martinez"), new Person("Paul", "Watson ") ); String joinedFirstNames = list.stream() .map(Person::getFirstName) .collect(Collectors.joining(", ")); // "John, Anna, Paul"The
StringJoinerкласс также может быть полезен.
все ссылки на Apache Commons прекрасны (и это то, что большинство людей используют), но я думаю, что гуавы эквивалентной Столяр, имеет гораздо более приятный API.
вы можете сделать простой случай соединения с
Joiner.on(" and ").join(names)но также легко иметь дело с нулями:
Joiner.on(" and ").skipNulls().join(names);или
Joiner.on(" and ").useForNull("[unknown]").join(names);и (достаточно полезно, насколько я могу использовать его в предпочтении к commons-lang), способность иметь дело с Карты:
Map<String, Integer> ages = .....; String foo = Joiner.on(", ").withKeyValueSeparator(" is ").join(ages); // Outputs: // Bill is 25, Joe is 30, Betty is 35что весьма полезно для отлаживать ЕТК.
не из коробки, но многие библиотеки имеют аналогичные:
Commons Lang:
org.apache.commons.lang.StringUtils.join(list, conjunction);Весна:
org.springframework.util.StringUtils.collectionToDelimitedString(list, conjunction);
нет, в стандартном Java API нет такого удобного метода.
неудивительно, что Apache Commons предоставляет такую вещь в их классе StringUtils в случае, если вы не хотите писать его самостоятельно.
три возможности в Java 8:
List<String> list = Arrays.asList("Alice", "Bob", "Charlie") String result = String.join(" and ", list); result = list.stream().collect(Collectors.joining(" and ")); result = list.stream().reduce((t, u) -> t + " and " + u).orElse("");
с коллектором java 8 это можно сделать с помощью следующего кода:
Arrays.asList("Bill", "Bob", "Steve").stream() .collect(Collectors.joining(" and "));кроме того, самое простое решение в java 8:
String.join(" and ", "Bill", "Bob", "Steve");или
String.join(" and ", Arrays.asList("Bill", "Bob", "Steve"));
я написал это (я использую его для бобов и exploit
toString, так что не пишитеCollection<String>):public static String join(Collection<?> col, String delim) { StringBuilder sb = new StringBuilder(); Iterator<?> iter = col.iterator(); if (iter.hasNext()) sb.append(iter.next().toString()); while (iter.hasNext()) { sb.append(delim); sb.append(iter.next().toString()); } return sb.toString(); }но
Collectionне поддерживается JSP, поэтому для TLD я написал:public static String join(List<?> list, String delim) { int len = list.size(); if (len == 0) return ""; StringBuilder sb = new StringBuilder(list.get(0).toString()); for (int i = 1; i < len; i++) { sb.append(delim); sb.append(list.get(i).toString()); } return sb.toString(); }и поставить
.tldfile:<?xml version="1.0" encoding="UTF-8"?> <taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" <function> <name>join</name> <function-class>com.core.util.ReportUtil</function-class> <function-signature>java.lang.String join(java.util.List, java.lang.String)</function-signature> </function> </taglib>и использовать его в файлах JSP как:
<%@taglib prefix="funnyFmt" uri="tag:com.core.util,2013:funnyFmt"%> ${funnyFmt:join(books, ", ")}
код у вас есть правильный способ сделать это, если вы хотите сделать с помощью JDK без каких-либо внешних библиотек. Нет простого "однострочного", который вы могли бы использовать в JDK.
Если вы можете использовать внешние библиотеки, я рекомендую вам заглянуть в орг.апаш.палата общин.ленг.StringUtils класс в библиотеке Apache Commons.
пример использования:
List<String> list = Arrays.asList("Bill", "Bob", "Steve"); String joinedResult = StringUtils.join(list, " and ");
ортодоксальный способ достичь этого - определить новую функцию:
public static String join(String join, String... strings) { if (strings == null || strings.length == 0) { return ""; } else if (strings.length == 1) { return strings[0]; } else { StringBuilder sb = new StringBuilder(); sb.append(strings[0]); for (int i = 1; i < strings.length; i++) { sb.append(join).append(strings[i]); } return sb.toString(); } }пример:
String[] array = new String[] { "7, 7, 7", "Bill", "Bob", "Steve", "[Bill]", "1,2,3", "Apple ][","~,~" }; String joined; joined = join(" and ","7, 7, 7", "Bill", "Bob", "Steve", "[Bill]", "1,2,3", "Apple ][","~,~"); joined = join(" and ", array); // same result System.out.println(joined);выход:
7, 7, 7 и Билл и Боб и Стив и [Билл] и 1,2,3 и Apple ][ и~,~
вы можете использовать библиотеку Apache commons, которая имеет класс StringUtils и метод join.
, проверьте эту ссылку: https://commons.apache.org/proper/commons-lang/javadocs/api.2.0/org/apache/commons/lang/StringUtils.html
обратите внимание, что ссылка выше может со временем устареть, и в этом случае вы можете просто искать в интернете "apache commons StringUtils", что должно позволить вам найти последнюю ссылку.
(ссылка из этого нитка) Java эквиваленты строки C#.Формат () и строка.Присоединяйтесь()
Java 8 решение с
java.util.StringJoinerJava 8 получил
StringJoinerкласса. Но вам все равно нужно написать немного шаблона, потому что это Java.StringJoiner sj = new StringJoiner(" and ", "" , ""); String[] names = {"Bill", "Bob", "Steve"}; for (String name : names) { sj.add(name); } System.out.println(sj);
Вы можете сделать это:
String aToString = java.util.Arrays.toString(anArray); // Do not need to do this if you are OK with '[' and ']' aToString = aToString.substring(1, aToString.length() - 1);или однострочный (только когда вы не хотите ' ['и']')
String aToString = java.util.Arrays.toString(anArray).substring(1).replaceAll("\]$", "");надеюсь, что это помогает.
интересный способ сделать это с чистым JDK, в одной служебной строке:
String[] array = new String[] { "Bill", "Bob", "Steve","[Bill]","1,2,3","Apple ][" }; String join = " and "; String joined = Arrays.toString(array).replaceAll(", ", join) .replaceAll("(^\[)|(\]$)", ""); System.out.println(joined);выход:
Билл и Боб и Стив и [Билл] и 1,2,3 и Apple ][
не слишком идеальный и не слишком интересный способ!
String[] array = new String[] { "7, 7, 7","Bill", "Bob", "Steve", "[Bill]", "1,2,3", "Apple ][" }; String join = " and "; for (int i = 0; i < array.length; i++) array[i] = array[i].replaceAll(", ", "~,~"); String joined = Arrays.toString(array).replaceAll(", ", join) .replaceAll("(^\[)|(\]$)", "").replaceAll("~,~", ", "); System.out.println(joined);выход:
7, 7, 7 и Билл и Боб и Стив и [Билл] и 1,2,3 и Apple ][
вы можете попробовать Apache Commons StringUtils метод соединения:
http://commons.apache.org/lang/api/org/apache/commons/lang/StringUtils.html#join(java.util.Iterator- Ява.ленг.Строка)
Я обнаружил, что Apache StringUtils поднимает слабину jdk; -)
если вы используете Коллекции Eclipse (ранее коллекции GS), вы можете использовать
makeString()метод.List<String> list = Arrays.asList("Bill", "Bob", "Steve"); String string = ListAdapter.adapt(list).makeString(" and "); Assert.assertEquals("Bill and Bob and Steve", string);если вы можете конвертировать ваши
Listк типу коллекций Eclipse, то вы можете избавиться от адаптера.MutableList<String> list = Lists.mutable.with("Bill", "Bob", "Steve"); String string = list.makeString(" and ");если вы просто хотите строку, разделенную запятыми, вы можете использовать версию
makeString(), который не принимает никаких параметров.Assert.assertEquals( "Bill, Bob, Steve", Lists.mutable.with("Bill", "Bob", "Steve").makeString());Примечание: я коммиттер для Eclipse Коллекции.
Google Guava API также имеет .join (), хотя (как должно быть очевидно с другими ответами), Apache Commons В значительной степени является стандартом здесь.
EDIT
Я также заметил, что
toString()основная проблема реализации, и об элементе, содержащем разделитель, но я думал, что я был параноиком.поскольку у меня есть два комментария по этому поводу, я меняю свой ответ на:
static String join( List<String> list , String replacement ) { StringBuilder b = new StringBuilder(); for( String item: list ) { b.append( replacement ).append( item ); } return b.toString().substring( replacement.length() ); }который выглядит довольно похожим на исходный вопрос.
поэтому, если вы не хотите добавлять всю банку в свой проект, вы можете использовать это.
Я думаю, что есть ничего плохого в вашем исходном коде. На самом деле, альтернатива, которую все предлагают, выглядит почти одинаково ( хотя она делает ряд дополнительных проверок )
вот он, вместе с Лицензия Apache 2.0.
public static String join(Iterator iterator, String separator) { // handle null, zero and one elements before building a buffer if (iterator == null) { return null; } if (!iterator.hasNext()) { return EMPTY; } Object first = iterator.next(); if (!iterator.hasNext()) { return ObjectUtils.toString(first); } // two or more elements StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small if (first != null) { buf.append(first); } while (iterator.hasNext()) { if (separator != null) { buf.append(separator); } Object obj = iterator.next(); if (obj != null) { buf.append(obj); } } return buf.toString(); }Теперь мы знаем, спасибо с открытым исходным кодом
С Java 1.8 поток может быть использован ,
import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; List<String> list = Arrays.asList("Bill","Bob","Steve"). String str = list.stream().collect(Collectors.joining(" and "));
Java 8 действительно приносит
Collectors.joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)метод, то есть nullsafe с помощью
prefix + suffixдля значения null.его можно использовать следующим образом:
String s = stringList.stream().collect(Collectors.joining(" and ", "prefix_", "_suffix"))The
Collectors.joining(CharSequence delimiter)метод просто называетjoining(delimiter, "", "")внутренне.
вы можете использовать это из StringUtils Spring Framework. Я знаю, что это уже упоминалось, но вы можете просто взять этот код, и он работает немедленно, без необходимости пружины для него.
// from https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/util/StringUtils.java /* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ public class StringUtils { public static String collectionToDelimitedString(Collection<?> coll, String delim, String prefix, String suffix) { if(coll == null || coll.isEmpty()) { return ""; } StringBuilder sb = new StringBuilder(); Iterator<?> it = coll.iterator(); while (it.hasNext()) { sb.append(prefix).append(it.next()).append(suffix); if (it.hasNext()) { sb.append(delim); } } return sb.toString(); } }
попробуйте это:
java.util.Arrays.toString(anArray).replaceAll(", ", ",") .replaceFirst("^\[","").replaceFirst("\]$","");
Comments