سؤال

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

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"));

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

هل كانت مفيدة؟

المحلول

والواقع، وربما كان وسيلة "أفضل" لتهيئة 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 التي لديها مهيئ سبيل المثال، ويتم إنشاء تلك الفئة فقط لخلق كائن واحد - الذي يبدو تماما مثل قليلا مبالغة بالنسبة لي.

وماذا كان لطيفا وإذا كان مجموعة الحرفية تم قبول الاقتراح للحصول على مشروع عملة (وكان من المقرر أن يتم عرضه في جافا 7، ولكن من غير المحتمل أن تكون جزءا من جافا 8 إما):.

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

ومما يؤسف له أنها لن تساعدك هنا، كما أنه سيتم تهيئة وList غير قابل للتغيير بدلا من ArrayList، وعلاوة على ذلك، انها ليست متاحة بعد، إذا كان أي وقت مضى وسوف.

نصائح أخرى

سيكون الأمر أسهل إذا أعلنت ذلك على أنه 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"));

الجواب البسيط

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

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

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

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

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


جافا 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 هو بالفعل قصير بما فيه الكفاية ويقرأ جيدا.


استخدام Streamس

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

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

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

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

(ربما لا تفعل ذلك.)
يقتبس جيب 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
}

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

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

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

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

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

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

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

في الجوافة وهناك أيضا منشئات ثابتة أخرى مفيدة. يمكنك أن تقرأ عنها هنا .

والحرفية مجموعة لم جعله جافا 8، ولكن من الممكن استخدام API تيار تهيئة قائمة في سطر واحد طويل إلى حد ما:

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

إذا كنت بحاجة للتأكد من أن List بك هو ArrayList:

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

....

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

مع Java 9, ، كما اقترح في اقتراح تعزيز JDK - 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")

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


البدائل

تم النظر في تغييرات اللغة عدة مرات، وتم رفضها:

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

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

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

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

ذات صلة => ما هو الهدف من أساليب مصنع الراحة المثقلة للمجموعات في Java 9

هل يمكن إنشاء أسلوب المصنع:

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;
}

في 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؟

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

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.

وحول الطريقة الأكثر المدمجة للقيام بذلك هي:

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

وهنا طريقة أخرى:

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

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

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

ويمكنك استخدام البيانات التالية:

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

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

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

و(يجب أن يكون للتعليق، ولكن وقتا طويلا، والرد الجديد نحو ذلك). كما ذكر آخرون، يتم إصلاح طريقة 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))

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

وكما قلت توم :

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

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

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

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

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

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 الخاص بك.

وP.S. أظهرت Randyaa طريقة أخرى لطيفة باستخدام طريقة فائدة ثابت <لأ href = "http://docs.oracle.com/javase /1.5.0/docs/api/java/util/Collections.html "يختلط =" نوفولو noreferrer "> Collections.addAll .

وجافا 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.

List<String> names = Arrays.asList("2","@2234","21","11");

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

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

وحاول مع هذا الخط كود:

Collections.singletonList(provider)

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

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

في جاوة، لا يمكنك أن تفعل

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").

وأيضا وفقا لجافادوك يجب أن تكون قادرة على القيام بذلك:

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

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

Collections.singletonList(messageBody)

إذا كنت بحاجة إلى قائمة شيء واحد!

المجموعات انه من java.util طَرد.

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

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);
    }
}

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

وهنا هو رمز بواسطة 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

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

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

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");

وأنا إنشاء قائمة من messageTemplate من ملف xml المخزنة في مسار قبل في سياق ثابت

public final class TemplateStore {

    private TemplateStore(){}

    private static final String [] VERSIONS = {"081"};
    private static final String TEMPLATE_FILE_MASK = "template/EdiTemplates_v%s.xml";
    private static final String ERROR = "Error In Building Edifact Message Template Store";

    public static final List<MessageTemplate> TEMPLATE_LIST = Arrays.stream(VERSIONS)
            .map(version -> TemplateStore.class
                    .getClassLoader().getResourceAsStream(String.format(TEMPLATE_FILE_MASK, version)))
            .map(inputStream -> {
                try {
                    return ((EdiTemplates) JAXBContext.newInstance(EdiTemplates.class).createUnmarshaller()
                            .unmarshal(inputStream)).getMessageTemplate();
                } catch (JAXBException e) {
                    throw new IllegalArgumentException(ERROR, e);
                }})
            .flatMap(Collection::stream)
            .collect(Collectors.toList());
}

والواقع، فمن الممكن أن تفعل ذلك في سطر واحد:

Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top