عكس قائمة في Java - في المكان وفي الخارج

في هذا البرنامج التعليمي القصير ، ستتعلم كيفية عكس القائمة في مكانها وخارجه في Java.

عكس في المكان وخارجه

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

تفضل بعض اللغات والمكتبات السلوكيات الافتراضية المختلفة. في Java ، ستكون معظم العمليات في القوائم العكسية في المكان.

إذا كان هذا هو السلوك الذي تريده - رائع! إذا لم يكن الأمر كذلك ، فستحتاج إلى إنشاء نسخة من القائمة قبل عكس النسخة:

List list = new ArrayList(Arrays.asList(1, 2, 3));
List listCopy = new ArrayList(list);

ملحوظة:clone() طريقة لا إنشاء نسخة عميقة. إنشاء قائمة باستخدام new ArrayList(list) لا إنشاء نسخة عميقة. لا يُنصح بإنشاء نسخ عميقة ، ومن المدهش أن يكون من الصعب القيام به بطريقة عامة (ولا يكون له معنى في بعض الحالات ، اعتمادًا على نوع (أنواع) البيانات في القائمة). لن يمنعك هذا من القدرة على الرجوع list و ليس تحتوي على عناصر listCopy على الرغم من عكس ذلك.

Collections.reverse ()

Collections.reverse() الطريقة هي الطريقة القياسية لعكس المجموعة ، وتعمل باعتبارها "المفقودة" List.reverse() طريقة. إنه يعكس القائمة في المكان:

List list = new ArrayList(Arrays.asList(1, 2, 3));
List listCopy = new ArrayList(list);

Collections.reverse(list);

System.out.println(list);     
System.out.println(listCopy); 

قوائم الجوافة. عكس (قائمة)

إذا كنت تستخدم Google Guava بالفعل في مشروعك ، فيمكنك أيضًا الاستفادة من Lists الصف الذي يقدم reverse() الأسلوب ، الذي لا يفرز القائمة الأصلية في نفس المكان ، ولكنه ينشئ نسخة ويعكس النسخة:

List list = new ArrayList(Arrays.asList(1, 2, 3));
List reversedList = Lists.reverse(list);

System.out.println(list);         
System.out.println(reversedList); 

إذا لم يكن لديك بالفعل ، يمكنك إضافة Google Guava إلى مشروعك باستخدام Maven ، من خلال تضمين تبعية في pom.xml ملف:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
</dependency>

أو عبر Gradle:

implementation group: 'com.google.guava', name: 'guava'

ملحوظة: إذا لم يكن لديك Google Guava بالفعل ، أو لا تنوي استخدامه لأجزاء أخرى من مشروعك - فلا تستورده لهذه العملية فقط ، والتزم بـ Collections.reverse() طريقة. الجوافة هي تبعية كبيرة ، ومن المبالغة استخدامها في هذه العملية فقط.

List.add () و List.remove ()

إذا كنت ترغب في إجراء عمليات إضافية إلى جانب عكس القائمة فقط - يمكنك تكرار القائمة الأصلية وإزالة العناصر من النهاية وتمريرها بطريقة عشوائية وإضافتها مرة أخرى في بداية القائمة:


public static int process(int input) {
    return input;
}

List list = new ArrayList(Arrays.asList(1, 2, 3));

for (int i = 0, j = list.size()-1; i <= j; i++) {
    int lastValue = process(list.remove(j));
    list.add(i, lastValue);
}

System.out.println(list);  

مؤشر

إذن ، ما هو الأسرع؟ يعتمد هذا أيضًا على ما إذا كنت تريد إجراء العملية في المكان أو في غير المكان.

معيار الانعكاس الموضعي

دعنا نقيس كلا النهجين على جميع الطرق الثلاثة ، بدءًا من خارج المكان:

List list = new Random().ints(100, 1, 11)
                .boxed()
                .collect(Collectors.toList());

int runs = 1000;

long start1 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    reverseListCollections(list);
}
long end1 = System.currentTimeMillis();
System.out.println(String.format("Collections.reverse() took: %s miliseconds", end1-start1));

long start2 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    reverseListGuava(list);
}
long end2 = System.currentTimeMillis();
System.out.println(String.format("Guava's Lists.reverse() took: %s miliseconds", end2-start2));

long start3 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    reverseListManually(list);
}
long end3 = System.currentTimeMillis();
System.out.println(String.format("Manually took: %s miliseconds", end3-start3));

System.out.println("Original list: " + list);

وينتج عنه:

Collections.reverse() took: 3 miliseconds
Guava's Lists.reverse() took: 4 miliseconds
Manually took: 13 miliseconds
Original list: [6, 7, 9, 7, 2, 5, 4, 1, 3, 2, 2, 6, ...

تحقق من دليلنا العملي العملي لتعلم Git ، مع أفضل الممارسات ، والمعايير المقبولة في الصناعة ، وورقة الغش المضمنة. توقف عن أوامر Googling Git وفي الواقع تعلم ذلك!

ماذا يحدث عندما نزيد عدد العناصر من 100 إلى 1000؟

Collections.reverse() took: 9 miliseconds
Guava's Lists.reverse() took: 4 miliseconds
Manually took: 133 miliseconds
Original list: [10, 2, 2, 6, 2, 4, 7, 3, 9, 2, 7, 5, ...

الجوافة تحتفظ بعلامة 4 ملي ثانية! النهج اليدوي لديه أسوأ تعقيد زمني ، وقد ارتفع بشكل خطي. Collections.reverse() تعاني أقل من التوسع ، لكن تنفيذ الجوافة يعاني أقل. رغم ذلك ، ضع في اعتبارك أننا لا ننسخ قائمة طريقة الجوافة يدويًا. هل سيتغير المعيار عندما نتخلى عن فكرة وجود قائمة "أصلية" و "معكوسة"؟

معيار الانعكاس في غير موضعه

مع 1000 عنصر ، وكل منها يعمل على نسخة غير معكوسة من القائمة (التي تم استبعادها من قياسات الوقت) ، عندما نزيل النسخة اليدوية من كل طريقة ونعيد تشغيل الكود:

Collections.reverse() took: 7 miliseconds
Guava's Lists.reverse() took: 3 miliseconds
Manually took: 131 miliseconds
Original list: [6, 8, 10, 7, 3, 8, 7, 1, 1, 9, 5, ...

جوافة لا يزال تمكن من التفوق باستمرار على كليهما Collections.reverse() والنهج اليدوي.

وفي الختام

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

الطابع الزمني:

اكثر من ستاكابوز