Soru Bir listeyi virgülle ayırmanın en net yolu?


Java'da bir listeyi virgülle ayırmanın en net yolu nedir?

Bunu yapmanın birkaç yolunu biliyorum, ama en iyi yolun ne olduğunu merak ediyorum (“en iyi” en net ve / veya en kısa değil, en verimli olanı ifade eder).

Bir listem var ve her bir değerin üzerine basmak istiyorum. Her bir öğe arasında virgül yazdırmak istiyorum, ancak sonuncusundan sonra (birinciden önce değil).

List --> Item ( , Item ) *
List --> ( Item , ) * Item

Örnek çözüm 1:

boolean isFirst = true;
for (Item i : list) {
  if (isFirst) {
    System.out.print(i);        // no comma
    isFirst = false;
  } else {
    System.out.print(", "+i);   // comma
  }
}

Örnek çözüm 2 - bir alt liste oluşturun:

if (list.size()>0) {
  System.out.print(list.get(0));   // no comma
  List theRest = list.subList(1, list.size());
  for (Item i : theRest) {
    System.out.print(", "+i);   // comma
  }
}

Örnek çözüm 3:

  Iterator<Item> i = list.iterator();
  if (i.hasNext()) {
    System.out.print(i.next());
    while (i.hasNext())
      System.out.print(", "+i.next());
  }

Bunlar ilk maddeyi özel olarak ele alır; Bunun yerine sonuncusu özel olarak tedavi edebilir.

Bu arada, işte nasıl? List  toString  olduğu uygulandı (bundan devralındı AbstractCollection), Java 1.6'da:

public String toString() {
    Iterator<E> i = iterator();
    if (! i.hasNext())
        return "[]";

    StringBuilder sb = new StringBuilder();
    sb.append('[');
    for (;;) {
        E e = i.next();
        sb.append(e == this ? "(this Collection)" : e);
        if (! i.hasNext())
            return sb.append(']').toString();
        sb.append(", ");
    }
}

Son maddeden sonra virgülden kaçınmak için döngüyü erken terk eder. BTW: Bu ilk kez gördüğüm zamanı hatırladım (bu Koleksiyon) "; Bunu provoke etmek için kod:

List l = new LinkedList();
l.add(l);
System.out.println(l);

Beklenmedik kütüphaneler kullanıyor olsalar bile (regexp?) Herhangi bir çözümü memnuniyetle karşılıyorum; ve ayrıca Java dışındaki dillerde çözümler (örn. Bence Python / Ruby'nin serpmek işlev - nasıl o hayata?).

açıklama: kütüphaneler tarafından, standart Java kütüphaneleri kastediyorum. Diğer kütüphaneler için bunları diğer dillerle değerlendiriyorum ve nasıl uygulandıklarını bilmek istiyorum.

DÜZENLE araç seti benzer bir soruya değindi: Java'da döngü için geliştirilmiş son yineleme

Ve başka: Bir döngüdeki son eleman ayrı bir tedaviyi hak ediyor mu?


96
2018-03-21 08:06


Menşei


Olası kopya Java'da bir dizi ayrılmış öğe oluşturmanın en iyi yolu nedir? - Raedwald


Cevaplar:


Java-8 öncesi için:

Ayrıca bakınız # 285523

String delim = "";
for (Item i : list) {
    sb.append(delim).append(i);
    delim = ",";
}

Java 8'den beri güncelleme:

kullanma StringJoiner :

StringJoiner joiner = new StringJoiner(",");
for (Item item : list) {
    joiner.add(item.toString());
}
return joiner.toString();

kullanma Akış, ve koleksiyoncular:

return list.stream().
       map(Object::toString).
       collect(Collectors.joining(",")).toString();

195
2018-03-21 11:44



Devlet depolamak için çok şaşırtıcı bir yol! Neredeyse OO polimorfik. Her döngüde gereksiz atamayı sevmiyorum, ama bahse girerim, eğer daha etkilidir. Çoğu çözüm, doğru olmayacağını bildiğimiz bir testi tekrarlıyor - verimsiz olsa da, muhtemelen en açık olanları. Link için teşekkürler! - 13ren
Bunu sevdim, ama zekice ve şaşırtıcı olduğu için, kullanımının uygun olmayacağını düşündüm (şaşırtıcı olan iyi değil!). Ancak kendime yardım edemedim. Hala bundan emin değilim; Ancak, o kadar kısa ki size bahşiş vermek için bir yorum yapılması koşuluyla çalışmak kolaydır. - 13ren
@ 13ren: Sen ve Bob Amca'nın "akıllı ve şaşırtıcı" bir kod hakkında konuşması gerekiyor. - Stefan Kendall
özlü ve temiz. - Jack
Bu ^^ bilmeyen yıllar harcadım gibi hissediyorum; - Lake


org.apache.commons.lang3.StringUtils.join(list,",");

78
2018-03-21 08:31



Kaynağı bulundu: svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/... Birleştirme yönteminde 9 aşırı yükleme var. Yinelemeye dayalı olanlar "Örnek çözüm 3" gibidir; dizin tabanlı olanlar şunları kullanır: if (i> startIndex) {<ayırıcı ekle>} - 13ren
Gerçekten de uygulamalardan sonra iyiyim. Bunu bir fonksiyona sarmak iyi bir fikirdir, fakat pratikte benim sınırlayıcım bazen yeni bir satırdır ve her satır da belirli bir derinliğe girintilidir. Katılmadıkça (liste, "\ n" + girinti) ... her zaman işe yarayacak mı? Üzgünüm, sadece sesli düşünüyorum. - 13ren
Daha fazla veya daha az standart kitaplık kullanmak için +1 - keuleJ
Benim düşünceme göre, bu en güzel ve en kısa çözüm - Jesper Rønn-Jensen
muhtemelen, list.iterator ()? - Vanuan


Java 8 bunu yapmak için birkaç yeni yol sunar:

  • join üzerinde yöntem String.
  • bir joining dan akış için toplayıcı Collectors sınıf.
  • StringJoiner sınıf.

Örnek:

// Util method for strings and other char sequences
List<String> strs = Arrays.asList("1", "2", "3");
String listStr1 = String.join(",", strs);

// For any type using streams and collectors
List<Object> objs = Arrays.asList(1, 2, 3);
String listStr2 = objs.stream().map(i -> i.toString()).collect(joining(",", "[", "]"));

// Using the new StringJoiner class
StringJoiner joiner = new StringJoiner(", ", "[", "]");
joiner.setEmptyValue("<empty>");
for (Integer i : objs) {
  joiner.add(i.toString());
}
String listStr3 = joiner.toString();

Akışları kullanan yaklaşım varsayılmaktadır import static java.util.stream.Collectors.joining;.


32
2017-09-02 13:26



Bu en iyi cevap java 8 kullanıyorsanız, bu IMHO. - scravy


Joiner.on(",").join(myList)

Marangoz.


17
2017-08-31 01:11



Tam olarak bunu yapan bir şey aramaya geldim. Teşekkürler! +1 - javamonkey79
Aynı. Bunun için teşekkürler. Sonunda, biri aklı başında. - T.W.R. Cole


Java'nın List toString uygulamasına göre:

Iterator i = list.iterator();
for (;;) {
  sb.append(i.next());
  if (! i.hasNext()) break;
  ab.append(", ");
}

Böyle bir gramer kullanır:

List --> (Item , )* Item

İlk tabanlı yerine son temelli olarak, listenin sonunu kontrol etmek için aynı testle atlama-virgülünü kontrol edebilir. Bunun çok zarif olduğunu düşünüyorum, ama açıklık konusunda emin değilim.


6
2018-03-21 11:04



Bu boş listeler için çalışmıyor. - Lii


Bahar Çerçevesini kullanırsanız bunu yapabilirsiniz StringUtils:

public static String arrayToDelimitedString(Object[] arr)
public static String arrayToDelimitedString(Object[] arr, String delim)
public static String collectionToCommaDelimitedString(Collection coll)
public static String collectionToCommaDelimitedString(Collection coll, String delim)

6
2018-03-21 16:10



Teşekkürler, ama nasıl uygulanır? - 13ren


String delimiter = ",";
StringBuilder sb = new StringBuilder();
for (Item i : list) {
    sb.append(delimiter).append(i);
}
sb.toString().replaceFirst(delimiter, "");

4
2017-08-27 16:42





Java 8 kullanarak bunu başarmanın güzel bir yolu var:

List<String> list = Arrays.asList(array);
String joinedString = String.join(",", list);

4
2018-05-09 13:49