Ik heb een ArrayList
die ik volledig als een string wil uitvoeren. In wezen wil ik het in volgorde uitvoeren met behulp van de toString
van elk element, gescheiden door tabs. Is er een snelle manier om dit te doen? Je zou er doorheen kunnen lopen (of elk element verwijderen) en het samenvoegen tot een string, maar ik denk dat dit erg traag zal zijn.
Antwoord 1, autoriteit 100%
Java 8 introduceert een String.join(separator, list)
methode; zie Vitalii Federenko’s antwoord.
Vóór Java 8 was het gebruik van een lus om de ArrayList
te herhalen de enige optie:
Gebruik deze code NIET, lees verder tot onderaan dit antwoord om te zien waarom het niet wenselijk is en welke code in plaats daarvan moet worden gebruikt:
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
String listString = "";
for (String s : list)
{
listString += s + "\t";
}
System.out.println(listString);
In feite zal een string-aaneenschakeling prima zijn, aangezien de javac
-compiler de string-concatenatie zal optimaliseren als een reeks append
-bewerkingen op een StringBuilder
toch. Hier is een deel van de demontage van de bytecode uit de for
-lus van het bovenstaande programma:
61: new #13; //class java/lang/StringBuilder
64: dup
65: invokespecial #14; //Method java/lang/StringBuilder."<init>":()V
68: aload_2
69: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
72: aload 4
74: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
77: ldc #16; //String \t
79: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
82: invokevirtual #17; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
Zoals te zien is, optimaliseert de compiler die lus door een StringBuilder
te gebruiken, dus prestaties zouden geen grote zorg moeten zijn.
(OK, op het tweede gezicht wordt de StringBuilder
geïnstantieerd bij elke iteratie van de lus, dus het is misschien niet de meest efficiënte bytecode. Instantie en gebruik van een expliciete StringBuilder
zou waarschijnlijk betere prestaties opleveren.)
In feite denk ik dat het hebben van elke vorm van uitvoer (of het nu naar schijf of naar het scherm is) op zijn minst een orde van grootte langzamer zal zijn dan dat je je zorgen hoeft te maken over de prestaties van string-aaneenschakelingen.
Bewerken:Zoals aangegeven in de opmerkingen, creëert de bovenstaande compileroptimalisatie inderdaad een nieuwe instantie van StringBuilder
bij elke iteratie. (Wat ik al eerder heb opgemerkt.)
De meest geoptimaliseerde techniek om te gebruiken is de reactie van Paul Tomblin, omdat het slechts een enkel StringBuilder
-object instantieert buiten de for
-lus.
Herschrijven naar de bovenstaande code om:
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
StringBuilder sb = new StringBuilder();
for (String s : list)
{
sb.append(s);
sb.append("\t");
}
System.out.println(sb.toString());
De StringBuilder
zal slechts eenmaal buiten de lus worden geïnstantieerd en alleen de twee aanroepen van de methode append
binnen de lus worden gedaan, zoals blijkt uit deze bytecode (die laat zien de instantie van StringBuilder
en de lus):
// Instantiation of the StringBuilder outside loop:
33: new #8; //class java/lang/StringBuilder
36: dup
37: invokespecial #9; //Method java/lang/StringBuilder."<init>":()V
40: astore_2
// [snip a few lines for initializing the loop]
// Loading the StringBuilder inside the loop, then append:
66: aload_2
67: aload 4
69: invokevirtual #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
72: pop
73: aload_2
74: ldc #15; //String \t
76: invokevirtual #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
79: pop
De handoptimalisatie zou dus inderdaad beter moeten presteren, aangezien de binnenkant van de for
-lus korter is en het niet nodig is om bij elke iteratie een StringBuilder
te maken.
Antwoord 2, autoriteit 97%
In Java 8 of hoger:
String listString = String.join(", ", list);
In het geval dat de list
niet van het type String is, kan een toetredende collector worden gebruikt:
String listString = list.stream().map(Object::toString)
.collect(Collectors.joining(", "));
Antwoord 3, autoriteit 94%
Als je dit toevallig op Android doet, is er een mooi hulpprogramma hiervoor genaamd TextUtilsmet een methode .join(String delimiter, Iterable)
.
List<String> list = new ArrayList<String>();
list.add("Item 1");
list.add("Item 2");
String joined = TextUtils.join(", ", list);
Natuurlijk niet veel gebruikt buiten Android, maar ik dacht ik voeg het toe aan deze thread…
Antwoord 4, autoriteit 67%
Download de Apache Commons Lang en gebruik de methode
StringUtils.join(list)
StringUtils.join(list, ", ") // 2nd param is the separator.
Je kunt het natuurlijk zelf implementeren, maar hun code is volledig getest en is waarschijnlijk de best mogelijke implementatie.
Ik ben een grote fan van de Apache Commons-bibliotheek en ik vind het ook een geweldige aanvulling op de Java Standard-bibliotheek.
Antwoord 5, autoriteit 39%
Dit is een vrij oude vraag, maar ik denk dat ik net zo goed een moderner antwoord kan toevoegen – gebruik de Joiner
-klasse van Guave:
String joined = Joiner.on("\t").join(list);
Antwoord 6, autoriteit 25%
Het veranderen van Lijstin een leesbare en betekenisvolle Stringis een veel voorkomende vraag die iedereen kan tegenkomen.
Geval 1. Als je StringUtils van apache in je klassenpad hebt (vanaf rogerdpack en Ravi Wallau):
import org.apache.commons.lang3.StringUtils;
String str = StringUtils.join(myList);
Geval 2. Als u alleen manieren uit JDK(7) wilt gebruiken:
import java.util.Arrays;
String str = Arrays.toString(myList.toArray());
Bouw nooit zelf wielen, gebruik geen lus voor deze taak van één regel.
Antwoord 7, autoriteit 18%
Als u op zoek was naar een snelle one-liner, kunt u vanaf Java 5 dit doen:
myList.toString().replaceAll("\\[|\\]", "").replaceAll(", ","\t")
Bovendien, als het uw doel is om alleen de inhoud af te drukken en u zich minder zorgen maakt over de “\t”, kunt u dit eenvoudig doen:
myList.toString()
die een tekenreeks retourneert zoals
[str1, str2, str3]
Als u een Array (niet ArrayList) heeft, kunt u hetzelfde als volgt bereiken:
Arrays.toString(myList).replaceAll("\\[|\\]", "").replaceAll(", ","\t")
Antwoord 8, autoriteit 11%
Loop er doorheen en bel tostring. Er is geen magische manier, en als er, wat denk je dat het zou doen onder de covers anders dan het doorlopen? Over de enige micro-optimalisatie zou zijn om stringbuilder te gebruiken in plaats van een string, en zelfs dat is geen enorme win-aaneengeschakelde snaren verandert in stringbuilder onder de dekens, maar tenminste als je het op die manier schrijft, kun je zien wat er aan de hand is.
StringBuilder out = new StringBuilder();
for (Object o : list)
{
out.append(o.toString());
out.append("\t");
}
return out.toString();
Antwoord 9, Autoriteit 10%
De meeste Java-projecten hebben vaak Apache-Commons Lang beschikbaar. StringUtils.join () Methoden zijn erg mooi en heeft verschillende smaken om bijna elke behoeften te ontmoeten.
public static java.lang.String join(java.util.Collection collection,
char separator)
public static String join(Iterator iterator, String separator) {
// handle null, zero and one elements before building a buffer
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();
}
Parameters:
Collection – De verzameling waarden om samen te voegen, kan null
zijn
scheidingsteken– het te gebruiken scheidingsteken
Retourneert: de samengevoegde string, null if
null iterator invoerSinds:
2.3
Antwoord 10, autoriteit 5%
Android heeft een TextUtil-klasse die u kunt gebruiken http://developer.android.com/reference/android /text/TextUtils.html
String implode = TextUtils.join("\t", list);
Antwoord 11, autoriteit 5%
Voor dit eenvoudige gebruik kun je de tekenreeksen eenvoudig samenvoegen met een komma. Als u Java 8 gebruikt:
String csv = String.join("\t", yourArray);
anders heeft commons-lang een join()-methode:
String csv = org.apache.commons.lang3.StringUtils.join(yourArray, "\t");
Antwoord 12, autoriteit 4%
Een elegante manier om met volgtekens om te gaan is door Klassescheidingsteken
StringBuilder buf = new StringBuilder();
Separator sep = new Separator("\t");
for (String each: list) buf.append(sep).append(each);
String s = buf.toString();
De methode toString van Class Separator retourneert de separator, behalvevoor de eerste aanroep. We drukken de lijst dus af zonder achterlopende (of in dit geval) voorloopscheidingstekens.
Antwoord 13, autoriteit 4%
In Java 8 is het eenvoudig. Zie voorbeeld voor lijst met gehele getallen:
String result = Arrays.asList(1,2,3).stream().map(Object::toString).reduce((t, u) -> t + "\t" + u).orElse("");
of multiline-versie (die eenvoudiger is om te lezen):
String result = Arrays.asList(1,2,3).stream()
.map(Object::toString)
.reduce((t, u) -> t + "\t" + u)
.orElse("");
Update – een kortere versie
String result = Arrays.asList(1,2,3).stream()
.map(Object::toString)
.collect(Collectors.joining("\t"));
Antwoord 14, Autoriteit 2%
Het is een O(n)
algoritme in beide richtingen (tenzij u een aantal multi-threaded oplossing hebt gedaan waar u de lijst in meerdere sublijsten hebt gebroken, maar ik denk niet dat dit is waar u om vraagt ).
Gebruik gewoon een StringBuilder
zoals hieronder:
StringBuilder sb = new StringBuilder();
for (Object obj : list) {
sb.append(obj.toString());
sb.append("\t");
}
String finalString = sb.toString();
De StringBuilder
is een stuk sneller dan string-aaneenvoeging omdat u geen onmiddellijk een String
Object op elke aaneenvoeging opnieuw kunt opnemen.
Antwoord 15
Als u toevallig op Android bent en u nog geen aansluiting gebruikt (bijvoorbeeld omdat het nog steeds ondersteuning biedt voor onmiddellijke run), en als u meer controle wilt over het formatteren van de resulterende tekenreeks (bijvoorbeeld u wilt gebruiken Newline-teken als de scheidingslijn van elementen), en toevallig de Streamsupport-bibliotheek (voor het gebruik van streams op Java 7 of eerdere versies van de compiler), kunt u zoiets gebruiken (ik heb deze methode in mijn Listutils-klasse gebruikt ):
public static <T> String asString(List<T> list) {
return StreamSupport.stream(list)
.map(Object::toString)
.collect(Collectors.joining("\n"));
}
En natuurlijk, zorg ervoor dat u TOSTRING () op uw lijst voor objectobjecten implementeert.
Antwoord 16
Als u niet wilt dat het laatste \ t na het laatste element, moet u de index gebruiken om te controleren, maar vergeet niet dat dit alleen “werken” (dwz o (n)) is wanneer de lijsten de willekeurige toerswerk implementeren.
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
StringBuilder sb = new StringBuilder(list.size() * apprAvg); // every apprAvg > 1 is better than none
for (int i = 0; i < list.size(); i++) {
sb.append(list.get(i));
if (i < list.size() - 1) {
sb.append("\t");
}
}
System.out.println(sb.toString());
Antwoord 17
in één regel:
Van [12,0,178,12] tot 12 0 1 78 12
String srt= list.toString().replaceAll("\\[|\\]|,","");
Antwoord 18
De onderstaande code kan u helpen,
List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
String str = list.toString();
System.out.println("Step-1 : " + str);
str = str.replaceAll("[\\[\\]]", "");
System.out.println("Step-2 : " + str);
Uitvoer:
Step-1 : [1, 2, 3]
Step-2 : 1, 2, 3
Antwoord 19
Misschien niet de beste manier, maar elegante manier.
Arrays.deepToString(Arrays.asList(“Test”, “Test2”)
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
System.out.println(Arrays.deepToString(Arrays.asList("Test", "Test2").toArray()));
}
}
Uitvoer
[Test, Test2]
Antwoord 20
Zou het volgende goed zijn:
List<String> streamValues = new ArrayList<>();
Arrays.deepToString(streamValues.toArray()));
Antwoord 21
Als je Eclipse Collectionsgebruikt, kun je de makeString()
methode.
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
Assert.assertEquals(
"one\ttwo\tthree",
ArrayListAdapter.adapt(list).makeString("\t"));
Als u uw ArrayList
kunt converteren naar een FastList
, kunt u de adapter verwijderen.
Assert.assertEquals(
"one\ttwo\tthree",
FastList.newListWith("one", "two", "three").makeString("\t"));
Opmerking: ik ben een toegewijde voor Eclipse Collections.
Antwoord 22
List<String> stringList = getMyListOfStrings();
StringJoiner sj = new StringJoiner(" ");
stringList.stream().forEach(e -> sj.add(e));
String spaceSeparated = sj.toString()
Je geeft aan de new StringJoiner
de tekenreeks door die je als scheidingsteken wilt gebruiken. Als je een CSV wilt maken: new StringJoiner(", ");
Antwoord 23
Voor het scheiden met tabbladen in plaats van printlnkunt u print
gebruiken
ArrayList<String> mylist = new ArrayList<String>();
mylist.add("C Programming");
mylist.add("Java");
mylist.add("C++");
mylist.add("Perl");
mylist.add("Python");
for (String each : mylist)
{
System.out.print(each);
System.out.print("\t");
}
Antwoord 24
Ik zie nogal wat voorbeelden die afhankelijk zijn van aanvullende bronnen, maar het lijkt erop dat dit de eenvoudigste oplossing zou zijn: (wat ik in mijn eigen project heb gebruikt) die in feite gewoon het converteren van een ArrayList naar een Array is en dan naar een lijst.
List<Account> accounts = new ArrayList<>();
public String accountList()
{
Account[] listingArray = accounts.toArray(new Account[accounts.size()]);
String listingString = Arrays.toString(listingArray);
return listingString;
}
Antwoord 25
Dit is nu nogal een oud gesprek en Apache Commons gebruiken nu intern een stringbuilder: http://commons.apache.org/lang/api/src-html/org/apache/commons/lang/stringutils.html#line.3045
Dit zal zoals we kennen de prestaties verbeteren, maar als de uitvoering van cruciaal belang is, kan de gebruikte methode enigszins inefficiënt zijn. Overwegende dat de interface flexibel is en een consistent gedrag in verschillende verzamelingstypen mogelijk maakt, is het enigszins inefficiënt voor lijsten, wat het type verzameling is in de oorspronkelijke vraag.
Ik baseer dit in dat we een beetje overhead gaan, die we zouden vermijden door simpelweg iteratie door de elementen in een traditioneel voor lus. In plaats daarvan gebeurt er nog meer dingen achter de schermen controleren op gelijktijdige aanpassingen, methode-oproepen enz. De verbeterde voor de lus zal aan de andere kant het gevolg zijn van dezelfde overhead, aangezien de iterator wordt gebruikt op het oerabebeleringsobject (de lijst).
Antwoord 26
U kunt hiervoor een regex gebruiken. Dit is net zo beknopt als het krijgt
System.out.println(yourArrayList.toString().replaceAll("\\[|\\]|[,][ ]","\t"));
Antwoord 27
Hoe zit het met deze functie:
public static String toString(final Collection<?> collection) {
final StringBuilder sb = new StringBuilder("{");
boolean isFirst = true;
for (final Object object : collection) {
if (!isFirst)
sb.append(',');
else
isFirst = false;
sb.append(object);
}
sb.append('}');
return sb.toString();
}
het werkt voor elk type verzameling…