मुझे String
जावा में दो सरणियों को संक्षिप्त करने की आवश्यकता है ।
void f(String[] first, String[] second) {
String[] both = ???
}
ऐसा करने का सबसे आसान तरीका क्या है?
array1 + array2
निष्कर्ष क्यों नहीं मिला ।
मुझे String
जावा में दो सरणियों को संक्षिप्त करने की आवश्यकता है ।
void f(String[] first, String[] second) {
String[] both = ???
}
ऐसा करने का सबसे आसान तरीका क्या है?
array1 + array2
निष्कर्ष क्यों नहीं मिला ।
जवाबों:
मुझे अच्छे पुराने अपाचे कॉमन्स लैंग लाइब्रेरी से एक-लाइन समाधान मिला।
ArrayUtils.addAll(T[], T...)
कोड:
String[] both = ArrayUtils.addAll(first, second);
यहां एक सरल विधि दी गई है जो दो सरणियों को सम्मिलित करेगी और परिणाम लौटाएगी:
public <T> T[] concatenate(T[] a, T[] b) {
int aLen = a.length;
int bLen = b.length;
@SuppressWarnings("unchecked")
T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen + bLen);
System.arraycopy(a, 0, c, 0, aLen);
System.arraycopy(b, 0, c, aLen, bLen);
return c;
}
ध्यान दें कि यह आदिम डेटा प्रकारों के साथ काम नहीं करेगा, केवल ऑब्जेक्ट प्रकारों के साथ।
निम्नलिखित थोड़ा अधिक जटिल संस्करण ऑब्जेक्ट और आदिम सरणियों दोनों के साथ काम करता है। यह तर्क प्रकार के T
बजाय का उपयोग करके ऐसा करता है T[]
।
यह परिणाम के घटक प्रकार के रूप में सबसे सामान्य प्रकार को उठाकर दो अलग-अलग प्रकारों के सरणियों को संक्षिप्त करना भी संभव बनाता है।
public static <T> T concatenate(T a, T b) {
if (!a.getClass().isArray() || !b.getClass().isArray()) {
throw new IllegalArgumentException();
}
Class<?> resCompType;
Class<?> aCompType = a.getClass().getComponentType();
Class<?> bCompType = b.getClass().getComponentType();
if (aCompType.isAssignableFrom(bCompType)) {
resCompType = aCompType;
} else if (bCompType.isAssignableFrom(aCompType)) {
resCompType = bCompType;
} else {
throw new IllegalArgumentException();
}
int aLen = Array.getLength(a);
int bLen = Array.getLength(b);
@SuppressWarnings("unchecked")
T result = (T) Array.newInstance(resCompType, aLen + bLen);
System.arraycopy(a, 0, result, 0, aLen);
System.arraycopy(b, 0, result, aLen, bLen);
return result;
}
यहाँ एक उदाहरण है:
Assert.assertArrayEquals(new int[] { 1, 2, 3 }, concatenate(new int[] { 1, 2 }, new int[] { 3 }));
Assert.assertArrayEquals(new Number[] { 1, 2, 3f }, concatenate(new Integer[] { 1, 2 }, new Number[] { 3f }));
Array.newInstance(a.getClass().getComponentType(), aLen + bLen);
। मैंने आश्चर्यजनक रूप से पहले कभी नहीं देखा है। @beaudet मुझे लगता है कि एनोटेशन यहाँ ठीक है, यह देखते हुए कि इसे क्यों दबाया जा रहा है।
यह पूरी तरह से सामान्य संस्करण लिखना संभव है जिसे किसी भी संख्या में सरणियों को बढ़ाने के लिए भी बढ़ाया जा सकता है। इस संस्करण को जावा 6 की आवश्यकता है, क्योंकि वे उपयोग करते हैंArrays.copyOf()
दोनों संस्करण किसी भी मध्यस्थ List
वस्तुओं को बनाने से बचते हैं और System.arraycopy()
यह सुनिश्चित करने के लिए उपयोग करते हैं कि बड़े सरणियों की नकल करना जितना संभव हो उतना तेज़ है।
दो सरणियों के लिए यह इस तरह दिखता है:
public static <T> T[] concat(T[] first, T[] second) {
T[] result = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, result, first.length, second.length);
return result;
}
और सरणियों की एक मनमानी संख्या के लिए (> = 1) यह इस तरह दिखता है:
public static <T> T[] concatAll(T[] first, T[]... rest) {
int totalLength = first.length;
for (T[] array : rest) {
totalLength += array.length;
}
T[] result = Arrays.copyOf(first, totalLength);
int offset = first.length;
for (T[] array : rest) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
T
को प्रतिस्थापित करें byte
(और खोएं <T>
)।
ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
concat(ai, ad)
, जहां ai
है Integer[]
और ad
है Double[]
। (इस मामले में, प्रकार पैरामीटर कंपाइलर द्वारा <T>
हल किया <? extends Number>
जाता है।) द्वारा बनाई गई Arrays.copyOf
सरणी Integer
में इस उदाहरण में पहले प्रकार का घटक प्रकार होगा । जब फ़ंक्शन दूसरे सरणी की प्रतिलिपि बनाने वाला होता है, तो एक ArrayStoreException
को फेंक दिया जाएगा। समाधान के लिए एक अतिरिक्त Class<T> type
पैरामीटर है।
Stream
जावा 8 में उपयोग करना :
String[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b))
.toArray(String[]::new);
या इस तरह, का उपयोग कर flatMap
:
String[] both = Stream.of(a, b).flatMap(Stream::of)
.toArray(String[]::new);
सामान्य प्रकार के लिए ऐसा करने के लिए आपको प्रतिबिंब का उपयोग करना होगा:
@SuppressWarnings("unchecked")
T[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(
size -> (T[]) Array.newInstance(a.getClass().getComponentType(), size));
.boxed()
इसलिए वे Stream
उदाहरण के बजाय टाइप के होते हैं, IntStream
जिन्हें पैरामीटर के रूप में पारित नहीं किया जा सकता है Stream.concat
।
a
और b
हैं int[]
, तो उपयोग करेंint[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
System.arrayCopy
। लेकिन विशेष रूप से धीमा भी नहीं है। संभवतः आपको निष्पादन के समय अंतर के मामले में वास्तव में संवेदनशील संदर्भों में विशाल सरणियों के साथ ऐसा बहुत बार करना पड़ता है।
या प्रिय अमरूद के साथ :
String[] both = ObjectArrays.concat(first, second, String.class);
इसके अलावा, आदिम सरणियों के लिए संस्करण हैं:
Booleans.concat(first, second)
Bytes.concat(first, second)
Chars.concat(first, second)
Doubles.concat(first, second)
Shorts.concat(first, second)
Ints.concat(first, second)
Longs.concat(first, second)
Floats.concat(first, second)
आप दो सरणियों को कोड की दो पंक्तियों में जोड़ सकते हैं।
String[] both = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, both, first.length, second.length);
यह एक तेज़ और कुशल समाधान है और यह आदिम प्रकारों के लिए काम करेगा और साथ ही इसमें शामिल दो तरीके अतिभारित होंगे।
आपको ArrayLists, स्ट्रीम इत्यादि से जुड़े समाधानों से बचना चाहिए क्योंकि ये बिना किसी उपयोगी उद्देश्य के लिए अस्थायी मेमोरी आवंटित करने की आवश्यकता होगी।
आपको for
बड़े सरणियों के लिए छोरों से बचना चाहिए क्योंकि ये कुशल नहीं हैं। बिल्ट-इन फ़ंक्शन का उपयोग ब्लॉक-कॉपी फ़ंक्शन का उपयोग करता है जो बहुत तेज़ हैं।
जावा एपीआई का उपयोग करना:
String[] f(String[] first, String[] second) {
List<String> both = new ArrayList<String>(first.length + second.length);
Collections.addAll(both, first);
Collections.addAll(both, second);
return both.toArray(new String[both.size()]);
}
both.toArray(new String[0])
से भी तेज होगा both.toArray(new String[both.size()])
, भले ही यह हमारे भोले अंतर्ज्ञान का विरोध करता हो। इसलिए अनुकूलन करते समय वास्तविक प्रदर्शन को मापना इतना महत्वपूर्ण है। या बस सरल निर्माण का उपयोग करें, जब अधिक जटिल संस्करण का लाभ सिद्ध नहीं किया जा सकता है।
एक समाधान 100% पुराना जावा और बिना System.arraycopy
(उदाहरण के लिए GWT क्लाइंट में उपलब्ध नहीं):
static String[] concat(String[]... arrays) {
int length = 0;
for (String[] array : arrays) {
length += array.length;
}
String[] result = new String[length];
int pos = 0;
for (String[] array : arrays) {
for (String element : array) {
result[pos] = element;
pos++;
}
}
return result;
}
null
चेक जोड़ना चाह सकते हैं । और शायद अपने कुछ चर सेट करें final
।
null
चेक्स उन्हें दिखाने के बजाय NPE को छुपाता था और स्थानीय वर्जन के लिए फाइनल का उपयोग करने से कोई लाभ (अभी तक) नहीं होता है।
मैंने हाल ही में अत्यधिक मेमोरी रोटेशन के साथ समस्याओं का सामना किया है। यदि ए और / या बी आमतौर पर खाली होने के लिए जाना जाता है, तो यहां सिलवर्टब कोड का एक और अनुकूलन है (जनरेट भी किया गया है):
private static <T> T[] concatOrReturnSame(T[] a, T[] b) {
final int alen = a.length;
final int blen = b.length;
if (alen == 0) {
return b;
}
if (blen == 0) {
return a;
}
final T[] result = (T[]) java.lang.reflect.Array.
newInstance(a.getClass().getComponentType(), alen + blen);
System.arraycopy(a, 0, result, 0, alen);
System.arraycopy(b, 0, result, alen, blen);
return result;
}
संपादित करें: इस पोस्ट के पिछले संस्करण में कहा गया है कि इस तरह से पुनः उपयोग स्पष्ट रूप से प्रलेखित किया जाएगा। के रूप में Maarten टिप्पणियों में बताते हैं कि यह सामान्य रूप से बेहतर होगा कि वे केवल बयानों को हटा दें, इस प्रकार दस्तावेज़ीकरण की आवश्यकता को शून्य कर दें। लेकिन फिर, अगर वे बयान पहली जगह में इस विशेष अनुकूलन के पूरे बिंदु थे। मैं इस जवाब को यहाँ छोड़ दूँगा, लेकिन सावधान रहना!
System.arraycopy
कि सरणी की सामग्री को कॉपी करता है?
if
बयानों को छोड़ना सबसे आसान तय होगा।
कार्यात्मक जावा पुस्तकालय एक सरणी आवरण वर्ग संयोजन की तरह काम के तरीकों के साथ सरणियों सज्जित है कि है।
import static fj.data.Array.array;
...और फिर
Array<String> both = array(first).append(array(second));
अलिखित सरणी वापस लाने के लिए, कॉल करें
String[] s = both.array();
ArrayList<String> both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));
both.toArray(new String[0]);
both.toArray(new String[both.size()])
;)
यहाँ जेनेरिक रेट्रोफ़िटेड के साथ सिल्वरटैब के घोल का रूपांतरण है:
static <T> T[] concat(T[] a, T[] b) {
final int alen = a.length;
final int blen = b.length;
final T[] result = (T[]) java.lang.reflect.Array.
newInstance(a.getClass().getComponentType(), alen + blen);
System.arraycopy(a, 0, result, 0, alen);
System.arraycopy(b, 0, result, alen, blen);
return result;
}
नोट: जावा 6 समाधान के लिए जोआचिम का उत्तर देखें । न केवल यह चेतावनी को समाप्त करता है; यह छोटा, अधिक कुशल और पढ़ने में आसान है!
यदि आप इस तरीके का उपयोग करते हैं तो आपको किसी भी तीसरे पक्ष के वर्ग को आयात करने की आवश्यकता नहीं है।
अगर आप कॉन्कैटनेट चाहते हैं String
संक्षिप्त स्ट्रिंग ऐरे के लिए नमूना कोड
public static String[] combineString(String[] first, String[] second){
int length = first.length + second.length;
String[] result = new String[length];
System.arraycopy(first, 0, result, 0, first.length);
System.arraycopy(second, 0, result, first.length, second.length);
return result;
}
अगर आप कॉन्कैटनेट चाहते हैं Int
संक्षिप्त कोडर दो ऐरे के लिए नमूना कोड
public static int[] combineInt(int[] a, int[] b){
int length = a.length + b.length;
int[] result = new int[length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
यहाँ मुख्य विधि है
public static void main(String[] args) {
String [] first = {"a", "b", "c"};
String [] second = {"d", "e"};
String [] joined = combineString(first, second);
System.out.println("concatenated String array : " + Arrays.toString(joined));
int[] array1 = {101,102,103,104};
int[] array2 = {105,106,107,108};
int[] concatenateInt = combineInt(array1, array2);
System.out.println("concatenated Int array : " + Arrays.toString(concatenateInt));
}
}
हम इस तरह से भी उपयोग कर सकते हैं।
कृपया मुझे पहले से ही लंबी सूची में एक और संस्करण जोड़ने के लिए क्षमा करें। मैंने हर उत्तर को देखा और निर्णय लिया कि मैं वास्तव में हस्ताक्षर में केवल एक पैरामीटर के साथ एक संस्करण चाहता हूं। मैंने अनपेक्षित इनपुट के मामले में समझदार जानकारी के साथ शुरुआती विफलता से लाभ के लिए कुछ तर्क की जाँच को भी जोड़ा।
@SuppressWarnings("unchecked")
public static <T> T[] concat(T[]... inputArrays) {
if(inputArrays.length < 2) {
throw new IllegalArgumentException("inputArrays must contain at least 2 arrays");
}
for(int i = 0; i < inputArrays.length; i++) {
if(inputArrays[i] == null) {
throw new IllegalArgumentException("inputArrays[" + i + "] is null");
}
}
int totalLength = 0;
for(T[] array : inputArrays) {
totalLength += array.length;
}
T[] result = (T[]) Array.newInstance(inputArrays[0].getClass().getComponentType(), totalLength);
int offset = 0;
for(T[] array : inputArrays) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
आप इसे एक Arraylist में बदलने की कोशिश कर सकते हैं और addAll पद्धति का उपयोग कर सकते हैं और फिर एक सरणी में बदल सकते हैं।
List list = new ArrayList(Arrays.asList(first));
list.addAll(Arrays.asList(second));
String[] both = list.toArray();
यहाँ सिल्वेतब द्वारा लिखित छद्म कोड समाधान के कामकाज कोड में एक संभावित कार्यान्वयन है।
धन्यवाद silvertab!
public class Array {
public static <T> T[] concat(T[] a, T[] b, ArrayBuilderI<T> builder) {
T[] c = builder.build(a.length + b.length);
System.arraycopy(a, 0, c, 0, a.length);
System.arraycopy(b, 0, c, a.length, b.length);
return c;
}
}
इसके बाद बिल्डर इंटरफ़ेस है।
नोट: एक बिल्डर आवश्यक है क्योंकि जावा में ऐसा करना संभव नहीं है
new T[size]
सामान्य प्रकार के क्षरण के कारण:
public interface ArrayBuilderI<T> {
public T[] build(int size);
}
यहाँ एक ठोस बिल्डर इंटरफ़ेस लागू कर रहा है, एक Integer
सरणी का निर्माण कर रहा है :
public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {
@Override
public Integer[] build(int size) {
return new Integer[size];
}
}
और अंत में आवेदन / परीक्षण:
@Test
public class ArrayTest {
public void array_concatenation() {
Integer a[] = new Integer[]{0,1};
Integer b[] = new Integer[]{2,3};
Integer c[] = Array.concat(a, b, new IntegerArrayBuilder());
assertEquals(4, c.length);
assertEquals(0, (int)c[0]);
assertEquals(1, (int)c[1]);
assertEquals(2, (int)c[2]);
assertEquals(3, (int)c[3]);
}
}
वाह! यहाँ बहुत से जटिल उत्तर दिए गए हैं, जिनमें कुछ सरल भी हैं जो बाहरी निर्भरता पर निर्भर हैं। यह इस तरह से करने के बारे में कैसे:
String [] arg1 = new String{"a","b","c"};
String [] arg2 = new String{"x","y","z"};
ArrayList<String> temp = new ArrayList<String>();
temp.addAll(Arrays.asList(arg1));
temp.addAll(Arrays.asList(arg2));
String [] concatedArgs = temp.toArray(new String[arg1.length+arg2.length]);
यह काम करता है, लेकिन आपको अपनी स्वयं की त्रुटि जांच सम्मिलित करने की आवश्यकता है।
public class StringConcatenate {
public static void main(String[] args){
// Create two arrays to concatenate and one array to hold both
String[] arr1 = new String[]{"s","t","r","i","n","g"};
String[] arr2 = new String[]{"s","t","r","i","n","g"};
String[] arrBoth = new String[arr1.length+arr2.length];
// Copy elements from first array into first part of new array
for(int i = 0; i < arr1.length; i++){
arrBoth[i] = arr1[i];
}
// Copy elements from second array into last part of new array
for(int j = arr1.length;j < arrBoth.length;j++){
arrBoth[j] = arr2[j-arr1.length];
}
// Print result
for(int k = 0; k < arrBoth.length; k++){
System.out.print(arrBoth[k]);
}
// Additional line to make your terminal look better at completion!
System.out.println();
}
}
यह शायद सबसे अधिक कुशल नहीं है, लेकिन यह जावा की अपनी एपीआई के अलावा किसी और चीज पर भरोसा नहीं करता है।
for
लूप को उस के साथ बदलना बेहतर होगा :for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)
पहला for
लूप स्किप करने के लिए उपयोग करें । के आकार के लिए आनुपातिक समय बचाता है arr1
।
यह स्ट्रिंग सरणी के लिए एक परिवर्तित कार्य है:
public String[] mergeArrays(String[] mainArray, String[] addArray) {
String[] finalArray = new String[mainArray.length + addArray.length];
System.arraycopy(mainArray, 0, finalArray, 0, mainArray.length);
System.arraycopy(addArray, 0, finalArray, mainArray.length, addArray.length);
return finalArray;
}
कैसे बस के बारे में
public static class Array {
public static <T> T[] concat(T[]... arrays) {
ArrayList<T> al = new ArrayList<T>();
for (T[] one : arrays)
Collections.addAll(al, one);
return (T[]) al.toArray(arrays[0].clone());
}
}
और बस करो Array.concat(arr1, arr2)
। जब तक arr1
और arr2
एक ही प्रकार के होते हैं, यह आपको एक ही प्रकार का एक और सरणी देगा जिसमें दोनों सरणियाँ होंगी।
एक सामान्य स्थैतिक संस्करण जो @SuppressWarnings एनोटेशन की आवश्यकता के बिना उच्च प्रदर्शन System.arraycopy का उपयोग करता है:
public static <T> T[] arrayConcat(T[] a, T[] b) {
T[] both = Arrays.copyOf(a, a.length + b.length);
System.arraycopy(b, 0, both, a.length, b.length);
return both;
}
public String[] concat(String[]... arrays)
{
int length = 0;
for (String[] array : arrays) {
length += array.length;
}
String[] result = new String[length];
int destPos = 0;
for (String[] array : arrays) {
System.arraycopy(array, 0, result, destPos, array.length);
destPos += array.length;
}
return result;
}
यहाँ जोछिम सॉर के कॉनसैट का मेरा थोड़ा बेहतर संस्करण है। यदि यह रनटाइम पर उपलब्ध है, तो यह जावा 6 के System.arraycopy का उपयोग करके जावा 5 या 6 पर काम कर सकता है। यह विधि (IMHO) Android के लिए एकदम सही है, क्योंकि यह Android <9 पर काम करता है (जिसमें System.arraycopy नहीं है) लेकिन यदि संभव हो तो तेज़ विधि का उपयोग करेगा।
public static <T> T[] concatAll(T[] first, T[]... rest) {
int totalLength = first.length;
for (T[] array : rest) {
totalLength += array.length;
}
T[] result;
try {
Method arraysCopyOf = Arrays.class.getMethod("copyOf", Object[].class, int.class);
result = (T[]) arraysCopyOf.invoke(null, first, totalLength);
} catch (Exception e){
//Java 6 / Android >= 9 way didn't work, so use the "traditional" approach
result = (T[]) java.lang.reflect.Array.newInstance(first.getClass().getComponentType(), totalLength);
System.arraycopy(first, 0, result, 0, first.length);
}
int offset = first.length;
for (T[] array : rest) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
सवाल के बारे में सोचने का दूसरा तरीका। दो या दो से अधिक सरणियों को सम्मिलित करने के लिए, प्रत्येक एरे के सभी तत्वों को सूचीबद्ध करना है, और फिर एक नई सरणी का निर्माण करना है। ऐसा लगता है कि एक बनाएँ List<T>
और फिर उस toArray
पर कॉल करें। कुछ अन्य उत्तर का उपयोग करता है ArrayList
, और यह ठीक है। लेकिन अपने खुद के कार्यान्वयन के बारे में कैसे? यह कठिन नहीं है:
private static <T> T[] addAll(final T[] f, final T...o){
return new AbstractList<T>(){
@Override
public T get(int i) {
return i>=f.length ? o[i - f.length] : f[i];
}
@Override
public int size() {
return f.length + o.length;
}
}.toArray(f);
}
मेरा मानना है कि उपरोक्त समाधानों के बराबर है जो उपयोग करता है System.arraycopy
। हालाँकि मुझे लगता है कि यह अपनी सुंदरता है।
कैसा रहेगा :
public String[] combineArray (String[] ... strings) {
List<String> tmpList = new ArrayList<String>();
for (int i = 0; i < strings.length; i++)
tmpList.addAll(Arrays.asList(strings[i]));
return tmpList.toArray(new String[tmpList.size()]);
}
एक से अधिक सरणी में शामिल होने की अनुमति देने वाला एक साधारण बदलाव:
public static String[] join(String[]...arrays) {
final List<String> output = new ArrayList<String>();
for(String[] array : arrays) {
output.addAll(Arrays.asList(array));
}
return output.toArray(new String[output.size()]);
}
केवल जाव्स के अपने एपीआई का उपयोग करना:
String[] join(String[]... arrays) {
// calculate size of target array
int size = 0;
for (String[] array : arrays) {
size += array.length;
}
// create list of appropriate size
java.util.List list = new java.util.ArrayList(size);
// add arrays
for (String[] array : arrays) {
list.addAll(java.util.Arrays.asList(array));
}
// create and return final array
return list.toArray(new String[size]);
}
अब, यह कोड सबसे अधिक कुशल नहीं है, लेकिन यह केवल मानक जावा कक्षाओं पर निर्भर करता है और समझने में आसान है। यह किसी भी संख्या में स्ट्रिंग [] (यहां तक कि शून्य सरणियों) के लिए भी काम करता है।