it-swarm.asia

تهيئة ArrayList في سطر واحد

أريد إنشاء قائمة خيارات لأغراض الاختبار. في البداية ، فعلت هذا:

ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");

ثم قمت بإعادة تشكيل الكود كما يلي:

ArrayList<String> places = new ArrayList<String>(
    Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

هل هناك طريقة أفضل للقيام بذلك؟

2465
Macarse

في الواقع ، ربما تكون الطريقة "الأفضل" لتهيئة ArrayList هي الطريقة التي كتبتها ، حيث إنها لا تحتاج إلى إنشاء List جديد بأي طريقة:

ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");

المهم هو أن هناك الكثير من الكتابة المطلوبة للإشارة إلى مثيل list.

هناك بدائل ، مثل إنشاء فئة داخلية مجهولة مع مُهيئ مثيل (المعروف أيضًا باسم "تهيئة دعامة مزدوجة"):

ArrayList<String> list = new ArrayList<String>() {{
    add("A");
    add("B");
    add("C");
}};

ومع ذلك ، لست مولعًا جدًا بهذه الطريقة لأن ما انتهى إليه الأمر هو فئة فرعية من ArrayList والتي تحتوي على مُهيئ مثيل ، ويتم إنشاء تلك الفئة فقط لإنشاء كائن واحد - يبدو ذلك كأنه مبالغة بالنسبة لي .

ما كان سيكون لطيفًا لو تم قبول اقتراح مجموعة المقتنيات لـ عملة المشروع (تم عرضه في Java 7 ، لكن من غير المحتمل أن يكون جزءًا من Java 8 أيضًا):

List<String> list = ["A", "B", "C"];

لسوء الحظ ، لن يساعدك ذلك هنا ، حيث إنه سيؤدي إلى تهيئة List غير قابل للتغيير بدلاً من ArrayList ، وعلاوة على ذلك ، فهو غير متوفر حتى الآن ، إذا كان متاحًا على الإطلاق.

1834
coobird

سيكون الأمر أكثر بساطة إذا كنت ستعلنها فقط كـ List - هل يجب أن تكون قائمة ArrayList؟

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

أو إذا كان لديك عنصر واحد فقط:

List<String> places = Collections.singletonList("Buenos Aires");

هذا يعني أن places هو غير قابل للتغيير (ستؤدي محاولة تغييره إلى استثناء UnsupportedOperationException).

لإنشاء قائمة قابلة للتغيير وهي ArrayList ، يمكنك إنشاء ArrayList من القائمة غير القابلة للتغيير:

ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
1945
Tom

الجواب بسيط

في Java 10 أو 11 أو 12 أو أحدث:

var strings = List.of("foo", "bar", "baz");

في Java 9 أو الأحدث:

List<String> strings = List.of("foo", "bar", "baz");

سيعطيك هذا List غير قابل للتغيير ، لذلك لا يمكن تغييره.
وهذا هو ما تريده في معظم الحالات حيث تقوم بجمعه مسبقًا.


Java 8 أو إصدار سابق:

List<String> strings = Arrays.asList("foo", "bar", "baz");

سيعطيك هذا List مدعومة بالصفيف ، لذلك لا يمكن تغيير الطول.
ولكن يمكنك الاتصال بـ List.set ، لذلك لا يزال قابلاً للتغيير.


يمكنك جعل Arrays.asList أقصر من خلال استيراد ثابت:

List<String> strings = asList("foo", "bar", "baz");

الاستيراد الثابت:

import static Java.util.Arrays.asList;  

أي حديث IDE سيقترح عليك وينفذها تلقائيًا لك.
على سبيل المثال في IntelliJ IDEA تضغط على Alt+Enter واختر Static import method....


ومع ذلك ، لا أوصي باختصار أسلوب Java 9 List.of ، لأن مجرد of يصبح مربكًا.
List.of بالفعل قصير بما فيه الكفاية ويقرأ جيدًا.


باستخدام Streams

لماذا يجب أن تكون List؟
باستخدام Java 8 أو إصدار أحدث ، يمكنك استخدام Stream وهو أكثر مرونة:

Stream<String> strings = Stream.of("foo", "bar", "baz");

يمكنك تسلسل Streams:

Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
                                       Stream.of("baz", "qux"));

أو يمكنك الانتقال من Stream إلى List:

import static Java.util.stream.Collectors.toList;

List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());

لكن من الأفضل أن تستخدم فقط Stream دون تجميعها على List.


إذا كنت {حقا تحتاج على وجه التحديد إلى Java.util.ArrayList

(ربما لا تفعل ذلك)
للإقتباس JEP 269 (لغم التشديد):

هناك مجموعة صغيرة من حالات الاستخدام لتهيئة مثيل مجموعة قابلة للتغيير مع مجموعة محددة مسبقًا من القيم. من المفضل عادة أن تكون تلك القيم المحددة مسبقًا في مجموعة غير قابلة للتغيير ، ثم تهيئة المجموعة القابلة للتغيير عبر مُنشئ نسخ.


إذا كنت ترغب في (كليهما إعداد مسبق لـ ArrayListو أضف إليه بعد ذلك (لماذا؟) ، استخدم

ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");

أو في Java 8 أو إصدار سابق:

ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");

أو استخدام Stream:

import static Java.util.stream.Collectors.toCollection;

ArrayList<String> strings = Stream.of("foo", "bar")
                             .collect(toCollection(ArrayList::new));
strings.add("baz");

لكن مرة أخرى ، من الأفضل أن تستخدم فقط Stream مباشرة بدلاً من تجميعها على List.


البرنامج إلى واجهات ، وليس للتطبيقات

لقد ذكرت أنك أعلنت أن القائمة ArrayList في شفرتك ، لكن يجب عليك القيام بذلك فقط إذا كنت تستخدم بعض أعضاء ArrayList غير موجود في List.

الذي أنت على الأرجح لا تفعل.

عادةً ما يجب عليك فقط الإعلان عن المتغيرات من خلال الواجهة الأكثر عمومية التي ستستخدمها (على سبيل المثال ، Iterable أو Collection أو List) ، وتهيئتها بالتطبيق المحدد (على سبيل المثال ArrayList أو LinkedList أو Arrays.asList()).

وإلا ، فأنت تقصر الشفرة الخاصة بك على هذا النوع المحدد ، وسيكون تغييره أمرًا صعبًا عندما تريد.

على سبيل المثال ، إذا كنت تقوم بتمرير ArrayList إلى void method(...):

// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) { 
    for (String s : strings) { ... } 
}

// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
    if (!strings.isEmpty()) { strings.stream()... }
}

// List if you also need .get(index):
void method(List<String> strings) {
    strings.get(...)
}

// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
    ??? // You don't want to limit yourself to just ArrayList
}

مثال آخر هو دائمًا التصريح عن المتغير بـ InputStream على الرغم من أنه عادةً FileInputStream أو BufferedInputStream ، لأنه في يوم قريب ستحتاج أنت أو شخص آخر لاستخدام نوع آخر من InputStream.

746
Christoffer Hammarström

إذا كنت بحاجة إلى قائمة بسيطة من الحجم 1:

List<String> strings = new ArrayList<String>(Collections.singletonList("A"));

إذا كنت بحاجة إلى قائمة بعدة كائنات:

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
106
Randyaa

مع الجوافة يمكنك الكتابة:

ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");

في جوافة هناك أيضا غيرها من الصانعين ثابت مفيد. يمكنك أن تقرأ عنها هنا .

54
Paweł Adamski

لم تدخل القيم الحرفية للمجموعة في Java 8 ، لكن من الممكن استخدام Stream API لتهيئة قائمة في سطر واحد بدلاً من ذلك:

List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());

إذا كنت بحاجة إلى التأكد من أن ListArrayList:

ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
32
Mark
import com.google.common.collect.ImmutableList;

....

List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
29
George

باستخدام Java 9 ، كما هو مقترح في JDK Enhancement Proposal - 269 ، يمكن تحقيق ذلك باستخدام مجموعة الحرفية الآن باسم -

List<String> list = List.of("A", "B", "C");

Set<String> set = Set.of("A", "B", "C");

كما سيتم تطبيق نهج مماثل على Map أيضًا -

Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")

وهو مشابه لـ اقتراح مجموعة Literals كما ذكرcoobird أيضًا. مزيد من التوضيح في وثيقة JEP كذلك -


البدائل

تم اعتبار التغييرات اللغوية عدة مرات ، ورفضت:

اقتراح عملة المشروع ، 29 مارس 2009

اقتراح عملة المشروع ، 30 مارس 2009

JEP 186 مناقشة حول lambda-dev ، من يناير إلى مارس 2014

تم وضع المقترحات اللغوية جانبًا في تفضيلها على اقتراح قائم على المكتبة كما هو موضح في هذه الرسالة .

Related => ما هي الفائدة من طرق مصنع الراحة الزائدة للمجموعات في Java 9

23
Naman

يمكنك إنشاء طريقة المصنع:

public static ArrayList<String> createArrayList(String ... elements) {
  ArrayList<String> list = new ArrayList<String>();
  for (String element : elements) {
    list.add(element);
  }
  return list;
}

....

ArrayList<String> places = createArrayList(
  "São Paulo", "Rio de Janeiro", "Brasília");

لكنها ليست أفضل بكثير من إعادة بيع المساكن الأولى.

لمزيد من المرونة ، يمكن أن يكون عامًا:

public static <T> ArrayList<T> createArrayList(T ... elements) {
  ArrayList<T> list = new ArrayList<T>();
  for (T element : elements) {
    list.add(element);
  }
  return list;
}
22
Jordão

في Java 9 ، يمكننا بسهولة تهيئة ArrayList في سطر واحد:

List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");

أو

List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));

هذا النهج الجديد لـ Java 9 له العديد من المزايا مقارنة بالمزايا السابقة:

  1. كفاءة الفضاء
  2. الثبات
  3. مؤشر ترابط الآمن

راجع هذا المنشور لمزيد من التفاصيل ->ما هو الفرق بين List.of و Arrays.asList؟

15
Mohit Tyagi

مع مجموعات Eclipse يمكنك كتابة ما يلي:

List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");

يمكنك أيضًا أن تكون أكثر تحديدًا حول الأنواع وعما إذا كانت قابلة للتغيير أو غير قابلة للتغيير.

MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");

يمكنك أيضًا أن تفعل الشيء نفسه مع مجموعات وحقائب:

Set<String> set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableSet<String> mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet<String> iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Bag<String> bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableBag<String> mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableBag<String> iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata");

ملاحظة: أنا مُلزم لمجموعة Eclipse Collections.

8
Donald Raab

إليك طريقة أخرى:

List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
7
Henok T

حول الطريقة الأكثر ضغطًا للقيام بذلك هي:

Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
7
Richard B

ببساطة استخدام رمز أدناه على النحو التالي.

List<String> list = new ArrayList<String>() {{
            add("A");
            add("B");
            add("C");
}};
7
user2801794

(يجب أن يكون تعليقًا ، ولكنه طويل جدًا ، رد جديد جدًا). كما ذكر الآخرون ، طريقة Arrays.asList هي حجم ثابت ، لكن هذه ليست المشكلة الوحيدة بها. كما أنها لا تتعامل مع الميراث بشكل جيد للغاية. على سبيل المثال ، افترض أن لديك ما يلي:

class A{}
class B extends A{}

public List<A> getAList(){
    return Arrays.asList(new B());
}

ما ورد أعلاه ينتج عنه خطأ في برنامج التحويل البرمجي ، لأن List<B> (والذي تم إرجاعه بواسطة Arrays.asList) ليس فئة فرعية من List<A> ، على الرغم من إمكانية إضافة كائنات من النوع B إلى كائن List<A>. للتغلب على هذا ، تحتاج إلى القيام بشيء مثل:

new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))

ربما هذه هي أفضل طريقة للقيام بذلك ، esp. إذا كنت بحاجة إلى قائمة غير محدودة أو تحتاج إلى استخدام الميراث.

6
user439407

يمكنك استخدام العبارات أدناه:

مقتطف الشفرة:

String [] arr = {"Sharlock", "Homes", "Watson"};

List<String> names = Arrays.asList(arr);
6
rashedcs

يحتوي Java 9 على الطريقة التالية لإنشاء غير قابل للتغيير قائمة:

List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");

التي يتم تكييفها بسهولة لإنشاء قائمة قابلة للتغيير ، إذا لزم الأمر:

List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));

تتوفر طرق مماثلة لـ Set و Map.

5
Carlos Heuberger

أعجبني قال توم :

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

ولكن نظرًا لأنك اشتكت من رغبتك في قائمة ArrayList ، فيجب أن تعرف أولاً أن ArrayList هي فئة فرعية من القائمة ويمكنك ببساطة إضافة هذا السطر:

ArrayList<String> myPlaces = new ArrayList(places);

على الرغم من أن هذا قد يجعلك تشكو من "الأداء".

في هذه الحالة ، ليس من المنطقي بالنسبة لي ، لماذا ، نظرًا لأن قائمتك محددة مسبقًا ، لم يتم تعريفها كصفيف (نظرًا لأن الحجم معروف في وقت التهيئة). وإذا كان هذا خيارًا لك:

String[] places = {"Buenos Aires", "Córdoba", "La Plata"};

في حال كنت لا تهتم باختلافات الأداء البسيطة ، يمكنك أيضًا نسخ صفيف إلى قائمة ArrayList بكل بساطة:

ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));

حسنًا ، لكن في المستقبل تحتاج إلى أكثر قليلاً من مجرد اسم المكان ، فأنت بحاجة إلى رمز البلد أيضًا. على افتراض أن هذه قائمة ما زالت محددة مسبقًا ولن تتغير أبدًا أثناء وقت التشغيل ، فمن المناسب استخدام مجموعة enum ، الأمر الذي سيتطلب إعادة التجميع إذا كانت القائمة بحاجة إلى تغيير في المستقبل.

enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}

قد يصبح:

enum Places {
    BUENOS_AIRES("Buenos Aires",123),
    CORDOBA("Córdoba",456),
    LA_PLATA("La Plata",789);

    String name;
    int code;
    Places(String name, int code) {
      this.name=name;
      this.code=code;
    }
}

يحتوي التعداد على طريقة values ثابتة تقوم بإرجاع صفيف يحتوي على جميع قيم التعداد بالترتيب الذي تم إعلانه به ، على سبيل المثال:

for (Places p:Places.values()) {
    System.out.printf("The place %s has code %d%n",
                  p.name, p.code);
}

في هذه الحالة أعتقد أنك لن تحتاج إلى قائمة ArrayList الخاصة بك.

ملاحظة أظهر Randyaa طريقة لطيفة أخرى باستخدام طريقة الأداة المساعدة الثابتة Collections.addAll .

5
Ozzy
List<String> names = Arrays.asList("2","@2234","21","11");
4
Ran Adler

يمكنك استخدام StickyList from Cactoos :

List<String> names = new StickyList<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);
4
yegor256

جرب باستخدام سطر الشفرة هذا:

Collections.singletonList(provider)
3
Ant20

نعم بمساعدة Arrays ، يمكنك تهيئة قائمة الصفيف في سطر واحد ،

List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
3
Akash Manngroliya

في Java ، لا يمكنك القيام بذلك

ArrayList<String> places = new ArrayList<String>( Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

كما تمت الإشارة إلى ذلك ، يلزمك إجراء تهيئة دعامة مزدوجة:

List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};

ولكن هذا قد يجبرك على إضافة تعليق توضيحي @SuppressWarnings("serial") أو إنشاء UUID مسلسل مزعج. كما أن معظم تنسيقات الأكواد سيتم فكها في عبارات/أسطر متعددة.

بدلا من ذلك يمكنك القيام به

List<String> places = Arrays.asList(new String[] {"x", "y" });

ولكن بعد ذلك قد ترغب في القيام @SuppressWarnings("unchecked").

وفقًا لـ javadoc ، يجب أن تكون قادرًا على القيام بذلك:

List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

لكنني غير قادر على الحصول على ترجمة مع JDK 1.6.

2
Dawg

أفضل طريقة للقيام بذلك:

package main_package;

import Java.util.ArrayList;


public class Stackkkk {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<Object>();
        add(list, "1", "2", "3", "4", "5", "6");
        System.out.println("I added " + list.size() + " element in one line");
    }

    public static void add(ArrayList<Object> list,Object...objects){
        for(Object object:objects)
            list.add(object);
    }
}

فقط قم بإنشاء وظيفة يمكن أن تحتوي على أكبر عدد تريده من العناصر واطلب منه إضافتها في سطر واحد.

1
EasyOdoo
Collections.singletonList(messageBody)

إذا كنت بحاجة إلى الحصول على قائمة عنصر واحد !

المجموعات هي من Java.util الحزمة.

1
ViliusK

هنا هو رمز بواسطة AbacusUtil

// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// Or for Immutable List/Set/Map
ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// The most efficient way, which is similar with Arrays.asList(...) in JDK. 
// but returns a flexible-size list backed by the specified array.
List<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");

إعلان : أنا المطور من AbacusUtil.

1
user_3380739

لماذا لا تجعل وظيفة الأداة المساعدة البسيطة التي تفعل هذا؟

static <A> ArrayList<A> ll(A... a) {
  ArrayList l = new ArrayList(a.length);
  for (A x : a) l.add(x);
  return l;
}

"ll" تعني "القائمة الحرفية".

ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");
0
Stefan Reich

بالنسبة لي Arrays.asList () هو الأفضل والملائم. أنا دائما أحب أن تهيئة بهذه الطريقة. إذا كنت مبتدئًا في مجموعات Java ، فإني أود منك الرجوع تهيئة ArrayList

0
Manoj Kumar