سؤال

هذا السؤال لديه بالفعل إجابة هنا:

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

ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)

for(String t : arr)
{
  t = " some other value "; //hoping this would change the actual array
}

for(String t : arr)
{
  System.out.println(t); //however, I still get the same array here
}

سؤالي هو كيف يمكنني جعل "t" مؤشرًا إلى "arr" حتى أتمكن من تغيير القيم في حلقة لكل حلقة؟أعلم أنه يمكنني التكرار خلال ArrayList باستخدام بنية مختلفة، ولكن هذه تبدو نظيفة جدًا وقابلة للقراءة، وسيكون من الجيد أن أتمكن من إنشاء مؤشر "t".

هي موضع تقدير جميع التعليقات!حتى لو قلت أنني يجب أن أتقبل الأمر وأستخدم بنية مختلفة.

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

المحلول

أعتقد أن أفضل طريقة هي استخدام حلقة for.

    ArrayList<String> arr = new ArrayList<String>();

    for (int i = 0; i < arr.size(); i++) {

        String t = arr.get(i);

        if (// your condition is met) {
            arr.set(i, "your new value");
        }
    }

نصائح أخرى

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

for (String t : arr) {
    t.set("some other value");
}

أو نحو ذلك، ولكن هذا غير ممكن لأنه غير قابل للتغيير.من الأفضل الحصول على مقبض نقطة الدخول في المصفوفة نفسها باستخدام القيمة العادية for حلقة:

for (int i = 0; i < arr.size(); i++) {
    arr.set(i, "some other value");
}

إذا كنت تصر على استخدام المحسن for حلقة، فأنت بحاجة إلى استبدال String بواسطة StringBuilder, ، وهو قابل للتغيير:

for (StringBuilder t : arr) {
     t.delete(0, t.length()).append("some other value");
}

تذكر أن Java عبارة عن قيمة تمريرية وليست مرجعية تمريرية.

لا يمنحك For-each مؤشر فهرس، لذا لا يمكنك استخدامه لتغيير قيمة غير قابلة للتغيير.

إما أن تستخدم حلقة for-loop مع فهرس أو تستخدم نوعًا قابلاً للتغيير (مثل StringBuffer، وليس String)

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

ما تفعله بنية for-each في Java هو إنشاء متغير محلي، ولكل تكرار، انسخ إلى هذا المتغير المحلي المرجع من خلية الصفيف الذي يتوافق مع هذا التكرار.عندما تقوم بتعيين متغير الحلقة (t = " some other value") أنت تضع إشارة إلى سلسلة جديدة، "some other value", ، في المتغير المحلي t، وليس في المصفوفة.

يتناقض مع بعض اللغات الأخرى (مثل Perl) حيث يعمل متغير الحلقة كاسم مستعار لعنصر المصفوفة/القائمة نفسه.

تتم إعادة كتابة التعليمات البرمجية الخاصة بك بواسطة المترجم على النحو التالي:

ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)

for (final Iterator <String> i = arr.iterator(); i.hasNext();) {
    String t;

    t = i.next();
    t = " some other value "; // just changes where t is pointing
}

لتفعل ما تريد، عليك أن تكتب حلقة for هكذا:

for (final ListIterator<String> i = arr.iterator(); i.hasNext();) {
     final String t;

     t = i.next();
     i.set("some other value");
}

لا يحتوي Iterator على الطريقة المحددة، فقط ListIterator هو الذي يمتلكها.

تريد في الأساس إزالة السلسلة t من القائمة.فقط قم بإجراء arr.remove(t) ويمكن أن يتم ذلك. لكن لا يمكنك القيام بذلك أثناء التكرار على نفس القائمة.سوف تحصل على استثناء إذا حاولت تعديل القائمة بهذه الطريقة.

لديك خياران:

  1. انسخ قائمتك، وكرر عملية الاستنساخ وأزل السلسلة "المحددة" من القائمة الأصلية
  2. قم بإنشاء قائمة لحذف المرشحين، وأضف جميع السلاسل "المحددة" إلى تلك القائمة، وبعد التكرار عبر القائمة الأصلية، قم بالتكرار عبر سلة المهملات وقم بإزالة كل ما قمت بجمعه هنا من القائمة الأصلية.

الخيار 1 هو الأسهل، ويمكن إجراء الاستنساخ مثل:

List<String> clone = new ArrayList<String>(arr);

يبدو أنك تسيء فهم كيفية عمل الكائنات/المراجع في Java، وهو أمر أساسي جدًا لاستخدام اللغة بفعالية.ومع ذلك، يجب أن يفعل هذا الرمز هنا ما تريد (نعتذر عن عدم وجود تفسير):

ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)

for(int i = 0; i < arr.size(); i++)
{
  arr.set(i, " some other value "); // change the contents of the array
}

for(String t : arr)
{
  System.out.println(t); 
}

أعتقد أن هذا لا يتعلق بغير قابل للتغيير أو التغيير.

 t = " some other value "; //hoping this would change the actual array

لا يحمل المرجع إلى الكائن الفعلي.تقوم Java بنسخ القيمة من arraylist وتضع هذه القيمة في t حتى لا تؤثر قيمة قائمة المصفوفات.

هث

وقد تم الرد على هذا بشكل جيد.لا يزال هنا اقتراحي.الحلقة الداخلية var t مرئية هناك فقط.لن يتم رؤيته خارج الحلقة.يمكنك أن تفعل t.set() إذا لم يكن كذلك String.

إستخدم StringBuffer بدلاً من السلاسل البسيطة.بهذه الطريقة تكون السلسلة الداخلية قابلة للتغيير.

السلاسل غير قابلة للتغيير.إذا كان لديك نوع قابل للتغيير مثل StringBuilder/Buffer، فيمكنك تغيير السلسلة في التكرار الخاص بك.لديك مراجع، تذكر.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top