Java: hàm cho các mảng như tham gia của PHP ()?


259

Tôi muốn tham gia String[]với một chuỗi keo. Có một chức năng cho điều này?


7
Java 8 có chức năng này bao gồm ngoài hộp. Tôi khuyên người đọc nên cuộn qua câu trả lời của @Marek Gregor (và upvote nó ..)
Stav

Câu trả lời:


307

Bắt đầu từ Java8 có thể sử dụng String.join().

String.join(", ", new String[]{"Hello", "World", "!"})

Tạo:

Hello, World, !

Mặt khác, Apache Commons Lang có một StringUtilslớp có joinchức năng sẽ nối các mảng lại với nhau để tạo thành một String.

Ví dụ:

StringUtils.join(new String[] {"Hello", "World", "!"}, ", ")

Tạo các mục sau String:

Hello, World, !

7
Vì lợi ích của những người tìm kiếm câu trả lời này, có lẽ nên lưu ý rằng đây cũng tương đương với tham gia Perl.
k-den

3
nó nói rằng nó không được xác định cho tôi
Ninjaxor

@Ninjaxor 1. commons-lang * jar phải nằm trong classpath 2. nhập org.apache.commons.lang3.StringUtils;
peterh - Phục hồi Monica

9
Tôi khuyên bạn nên chỉnh sửa câu trả lời này để nối thêm một tham chiếu đến String.join()phương thức mới được giới thiệu trong Java 8. Bằng cách này, số lượng lớn người đọc câu trả lời được chấp nhận này sẽ được hưởng lợi từ kiến ​​thức đó. Hiện tại, câu trả lời được bình chọn cao nhất đề cập đến thực tế này là khá lạc lõng bên dưới ...
Duncan Jones

1
Điều đáng nói là String.join()sẽ chỉ hoạt động cho List<CharSequence>hoặc CharSequence[]các yếu tố.
Enigo

71

Nếu bạn đang tìm kiếm những gì để sử dụng trong Android, đó là:

String android.text.TextUtils.join(CharSequence delimiter, Object[] tokens)

ví dụ:

String joined = TextUtils.join(";", MyStringArray);

2
Đây rõ ràng là câu trả lời tốt nhất cho tất cả các phiên bản Android, vì Java 8 chỉ mới xuất hiện trên Android một chút. Giải pháp này sử dụng các lib được tích hợp trong Android, thay vì các giải pháp "bao gồm một lib khổng lồ để thực hiện một hành động".
LukeStoneHm

Đó là tháng 9 năm 2017, Java 8 cho Android vẫn còn rất xa. Cảm ơn câu trả lời này!
Aenadon


53

Bạn có thể dễ dàng viết một hàm như vậy trong khoảng mười dòng mã:

String combine(String[] s, String glue)
{
  int k = s.length;
  if ( k == 0 )
  {
    return null;
  }
  StringBuilder out = new StringBuilder();
  out.append( s[0] );
  for ( int x=1; x < k; ++x )
  {
    out.append(glue).append(s[x]);
  }
  return out.toString();
}

35
Thực hành tốt theo bạn ... không có tiêu chuẩn chung cho những điều như vậy.
phoebus

24
Nhưng nếu tôi bao gồm cả niềng răng, điều đó sẽ thêm hai dòng mã nữa và tôi không thể tuyên bố đã thực hiện nó trong 11 dòng!
Jay

8
vấn đề là khi bạn sau một thời gian, hoặc người khác, vội vàng, thêm một dòng khác vào đó nếu / cho mà không thêm dấu ngoặc; hoặc xóa return null sau if (k == 0), trong một số trường hợp, nó sẽ biên dịch nhưng sẽ không chính xác. Sau đó, tốt hơn là hy sinh thêm một dòng cho cú đúp kết thúc đó (việc mở có thể giữ nguyên nếu / cho dòng).
milan

16
Tôi nghĩ thật tuyệt vời khi hầu hết các ngôn ngữ đều tích hợp chức năng như vậy vào cốt lõi của họ, cộng đồng Java khuyến khích mọi người phát minh lại bánh xe.
John Strickler

33
11 dòng? Bah! Tôi có thể làm điều đó trong 1! Chỉ cần xóa tất cả các ký tự dòng mới trong tệp nguồn.
Thomas Eding

25

Một chút mod thay vì sử dụng chuỗi con ():

//join(String array,delimiter)
public static String join(String r[],String d)
{
        if (r.length == 0) return "";
        StringBuilder sb = new StringBuilder();
        int i;
        for(i=0;i<r.length-1;i++){
            sb.append(r[i]);
            sb.append(d);
        }
        sb.append(r[i]);
        return sb.toString();
}

Bỏ phiếu vì bạn không cần thêm bất kỳ thư viện nào.
givanse

10
Dòng 7: Sẽ tốt hơn nếu được sử dụng .append()hai lần cho mỗi Stringthay vì nối chúng và sau đó nối vào trình tạo.
Talha Ahmed Khan

18

Như nhiều câu hỏi gần đây, Java 8 để giải cứu:


Java 8 đã thêm một phương thức tĩnh mới để java.lang.Stringthực hiện chính xác những gì bạn muốn:

public static String join(CharSequence delimeter, CharSequence... elements);

Sử dụng nó:

String s = String.join(", ", new String[] {"Hello", "World", "!"});

Kết quả trong:

"Hello, World, !"

14

Thư viện ổi của Google cũng có loại khả năng này . Bạn cũng có thể xem ví dụ Chuỗi [] từ API.

Như đã được mô tả trong api, hãy cẩn thận với tính bất biến của các phương thức xây dựng.

Nó có thể chấp nhận một loạt các đối tượng để nó hoạt động trong trường hợp của bạn. Theo kinh nghiệm trước đây của tôi, tôi đã thử tham gia một Stack có thể lặp lại và nó hoạt động tốt.

Mẫu từ tôi:

Deque<String> nameStack = new ArrayDeque<>();
nameStack.push("a coder");
nameStack.push("i am");
System.out.println("|" + Joiner.on(' ').skipNulls().join(nameStack) + "|");

in ra: |i am a coder|


9

Được:

String[] a = new String[] { "Hello", "World", "!" };

Sau đó, như là một thay thế cho câu trả lời của coobird, nơi keo là ",":

Arrays.asList(a).toString().replaceAll("^\\[|\\]$", "")

Hoặc để nối với một chuỗi khác, chẳng hạn như "& amp;".

Arrays.asList(a).toString().replaceAll(", ", " &amp; ").replaceAll("^\\[|\\]$", "")

Tuy nhiên ... CHỈ cái này hoạt động nếu bạn biết rằng các giá trị trong mảng hoặc danh sách KHÔNG chứa chuỗi ký tự ",".


Arrays.asList(a).toString()làm việc cho những gì tôi muốn làm
Solomon Ucko

9

Nếu bạn đang sử dụng Spring Framework thì bạn có lớp StringUtils :

import static org.springframework.util.StringUtils.arrayToDelimitedString;

arrayToDelimitedString(new String[] {"A", "B", "C"}, "\n");

8

Không trong cốt lõi, không. Một tìm kiếm cho "java mảng nối chuỗi keo" sẽ cung cấp cho bạn một số đoạn mã về cách để đạt được điều này mặc dù.

ví dụ

public static String join(Collection s, String delimiter) {
    StringBuffer buffer = new StringBuffer();
    Iterator iter = s.iterator();
    while (iter.hasNext()) {
        buffer.append(iter.next());
        if (iter.hasNext()) {
            buffer.append(delimiter);
        }
    }
    return buffer.toString();
}

2
Sử dụng StringBuilder (không an toàn luồng) thay cho StringBuffer (an toàn luồng) để có hiệu suất tốt hơn. Giao diện giống nhau.
Asaph

2
Đây dường như là từ snippets.dzone.com/posts/show/91 . Các ý kiến ​​đề xuất một phiên bản cải tiến hơn nhiều: tham gia Chuỗi tĩnh công khai (Iterable <? Extends Object> pColl, String separator) {Iterator <? mở rộng Object> oIter; if (pColl == null || (! (oIter = pColl.iterator ()) .hasNext ())) return ""; StringBuilder oBuilder = new StringBuilder (String.valueOf (oIter.next ())); while (oIter.hasNext ()) oBuilder.append (separator) .append (oIter.next ()); trả về oBuilder.toString (); }
Quantum7

6

Nếu bạn đã đến đây để tìm kiếm chuyển đổi mảng thành chuỗi nhanh, hãy thử Arrays.toString () .

Tạo một đại diện Chuỗi của Object[]thông qua. Kết quả được bao quanh bởi ngoặc ( "[]"), mỗi phần tử được chuyển đổi thành Chuỗi thông qua String.valueOf(Object)và được phân tách bằng ", ". Nếu mảng là null, sau đó "null"được trả lại.


CẢM ƠN RẤT NHIỀU! Các chuỗi được phân tách bằng "," và toàn bộ điều có "[]" xung quanh nó, điều này rất tốt với tôi.
John Henckel

5

Chỉ dành cho thử thách "Tôi là người ngắn nhất" , đây là mỏ;)

Lặp lại:

public static String join(String s, Object... a) {
    StringBuilder o = new StringBuilder();
    for (Iterator<Object> i = Arrays.asList(a).iterator(); i.hasNext();)
        o.append(i.next()).append(i.hasNext() ? s : "");
    return o.toString();
}

Đệ quy:

public static String join(String s, Object... a) {
    return a.length == 0 ? "" : a[0] + (a.length == 1 ? "" : s + join(s, Arrays.copyOfRange(a, 1, a.length)));
}

2
Phiên bản đệ quy là thanh lịch. Chắc chắn sẽ sử dụng điều đó.
Pete

Phiên bản đệ quy có thể thanh lịch, nhưng không hiệu quả đối với các mảng lớn (" copyOfRange()").
Ogre Psalm33


4

Đây là cách tôi làm điều đó.

private String join(String[] input, String delimiter)
{
    StringBuilder sb = new StringBuilder();
    for(String value : input)
    {
        sb.append(value);
        sb.append(delimiter);
    }
    int length = sb.length();
    if(length > 0)
    {
        // Remove the extra delimiter
        sb.setLength(length - delimiter.length());
    }
    return sb.toString();
}

2

Một sự thay thế tương tự

/**
 * @param delimiter 
 * @param inStr
 * @return String
 */
public static String join(String delimiter, String... inStr)
{
    StringBuilder sb = new StringBuilder();
    if (inStr.length > 0)
    {
        sb.append(inStr[0]);
        for (int i = 1; i < inStr.length; i++)
        {
            sb.append(delimiter);                   
            sb.append(inStr[i]);
        }
    }
    return sb.toString();
}

2

Vòng quay của tôi.

public static String join(Object[] objects, String delimiter) {
  if (objects.length == 0) {
    return "";
  }
  int capacityGuess = (objects.length * objects[0].toString().length())
      + ((objects.length - 1) * delimiter.length());
  StringBuilder ret = new StringBuilder(capacityGuess);
  ret.append(objects[0]);
  for (int i = 1; i < objects.length; i++) {
    ret.append(delimiter);
    ret.append(objects[i]);
  }
  return ret.toString();
}

public static String join(Object... objects) {
  return join(objects, "");
}

1

Bạn có thích cách 3 dòng của tôi chỉ sử dụng các phương thức của lớp String không?

static String join(String glue, String[] array) {
    String line = "";
    for (String s : array) line += s + glue;
    return (array.length == 0) ? line : line.substring(0, line.length() - glue.length());
}

1
Nó không có nghĩa là hiệu quả. Sử dụng StringBuildernếu bạn cần hiệu quả: P
Ryoichiro Oka

0

Để nhận "str1, str2" từ "str1", "str2", "":

Stream.of("str1", "str2", "").filter(str -> !str.isEmpty()).collect(Collectors.joining(", ")); 

Ngoài ra, bạn có thể thêm kiểm tra null


0

Trong trường hợp bạn đang sử dụng thư viện Java chức năng và vì một số lý do không thể sử dụng Luồng từ Java 8 (có thể là trường hợp khi sử dụng plugin Android + Retrolambda), đây là một giải pháp chức năng dành cho bạn:

String joinWithSeparator(List<String> items, String separator) {
    return items
            .bind(id -> list(separator, id))
            .drop(1)
            .foldLeft(
                    (result, item) -> result + item,
                    ""
            );
}

Lưu ý rằng đó không phải là cách tiếp cận hiệu quả nhất, nhưng nó hoạt động tốt cho các danh sách nhỏ.


-1

Tôi làm theo cách này bằng StringBuilder:

public static String join(String[] source, String delimiter) {
    if ((null == source) || (source.length < 1)) {
        return "";
    }

    StringBuilder stringbuilder = new StringBuilder();
    for (String s : source) {
        stringbuilder.append(s + delimiter);
    }
    return stringbuilder.toString();
} // join((String[], String)

1
s + delimiter(nối chuỗi với toán tử cộng) đánh bại toàn bộ mục đích sử dụng a StringBuilder.
quietmint

Thêm vào đó, cách tiếp cận này có nghĩa là một mảng như: {"foo", "bar"} với dấu phân cách ":" sẽ được chuyển thành "foo: bar:"
pioto

-2

Có một kỹ thuật tốc ký đơn giản mà tôi sử dụng hầu hết thời gian ..

String op = new String;
for (int i : is) 
{
    op += candidatesArr[i-1]+",";
}
op = op.substring(0, op.length()-1);

Điều này chỉ hoạt động với các dấu phân cách có độ dài 1 và yêu cầu 'số ma thuật' (mặc dù khá cục bộ) nếu bạn muốn một dấu phân cách có độ dài khác nhau.
maiwald

Bạn có thể thêm nhiều nhân vật trong khi nối thêm
Gaurav Adurkar

đơn giản hơn là: op = op.subopes (0, op.length () - ",". length ()); vấn đề lớn là gì?
Dennis

-3

java.util.Arrays có phương thức 'asList'. Cùng với API java.util.List / ArrayList, nó cung cấp cho bạn tất cả những gì bạn cần:;

private static String[] join(String[] array1, String[] array2) {

    List<String> list = new ArrayList<String>(Arrays.asList(array1));
    list.addAll(Arrays.asList(array2));
    return list.toArray(new String[0]);
}

7
Câu hỏi là làm thế nào để nối một mảng chuỗi với một dấu phân cách, chứ không phải làm thế nào để nối hai mảng chuỗi với nhau.
toolbear
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.