نمایش نتایج 1 تا 8 از 8

نام تاپیک: مشکل در کار با لیستها

  1. #1
    کاربر دائمی آواتار ehsan_faal
    تاریخ عضویت
    خرداد 1392
    محل زندگی
    تهران
    پست
    325

    مشکل در کار با لیستها

    سلام دوستان.
    سوالم اینه که چرا وقتی یه لیست رو میریزیم توی یه لیست دیگه و بعدش لیست اولیه رو پاک میکنیم لیستی هم که قراره محتویات لیست قبلی رو داشته باشه حذف میشه؟
    من یه همچین ترفندی رو واسه برنامم نیاز دارم اما متاسفانه بعد از پاک کردن لیست اولیه لیست جدید هم پاک میشه!

    List<Integer> First=new ArrayList<>();
    for(int Index=0;Index<10;Index++){
    First.add(Index, Index);
    }
    List<Integer> Second=new ArrayList<>();
    Second=First;
    System.out.println("First List: "+First);
    First.clear();
    System.out.println(Second);


    خروجی:
    First List: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    []

  2. #2

    نقل قول: مشکل در کار با لیستها

    سلام. به این خاطر که وقتی میگی Second = First شیء Second دوباره از روی First ساخته نمی‌شه بلکه فقط اشاره‌گر First در Second هم قرار می‌گیره... برای اینکار باید به‌طور کلی Second رو از اول از روی First بسازی. یعنی دستور Second = First رو حذف کن و خط ۵ رو به این شکل تغییر بده:
    List<Integer> Second = new ArrayList<>(First);

    البته توجه داشته باش که اینکار خصوصا برای لیست‌های بزرگ خیلی پرهزینه‌ست و بهتره کمتر اینکار رو بکنی. مثلا یه پیشنهاد می‌تونه این باشه که همونطور که خودت نوشته بودی صرفا اشاره‌گر First رو به Second انتقال بدی و در عوض First رو کلا از اول بسازی تا تبدیل به یه لیست خالی بشه:
    List<Integer> Second = First;
    First = new ArrayList<>();

    موفق باشی.
    اگر به بهداشت و سلامت حیوانات علاقه دارید، از vetMD.ir دیدن کنید.
    وبلاگ شخصی من: fadavi.net

    اینجا کمتر سر می‌زنم. (تلگرام من)

  3. #3
    کاربر دائمی آواتار ahmad.mo74
    تاریخ عضویت
    مرداد 1393
    محل زندگی
    تهران
    پست
    437

    نقل قول: مشکل در کار با لیستها

    سلام

    در ادامه صحبت های آقای فدوی، یه روش قشنگ تری هم برای copy کردن (بهتره سراغ clone کردن نری) یه Collection میتونه این باشه :


    public static <E, C extends Collection<E>> C convert(Iterable<?> from, C to, Class<E> listClass) {
    for (Object item : from) {
    to.add(listClass.cast(item));
    }
    return to;
    }


    خوبی این روش اینه که از هر Collection ای که بخوای به هر Collection دیگه ای میتونی کپی کنی و اینکه type-safe هم هست این روش. مثال :


    public static void main(String[] args) throws IOException {
    List<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    List<String> copyList = convert(list, new ArrayList<>(), String.class);
    list.clear();
    System.out.println(copyList);
    }



    public static void main(String[] args) throws IOException {
    List<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    Set<String> set = convert(list, new TreeSet<>(), String.class);
    list.clear();
    System.out.println(set);
    }


    خیلی وقتا میشه که از یه قسمتی از برنامه یا فریم ورکی که باهاش کار میکنی، list ای بهت بده که نوعش مشخص نیست و وقتی باهاش کار میکنی بخاطر type-safe نبودن دائما با اخطار ide روبرو میشی و مجبوری از
    @SuppressWarnings("unchecked")
    استفاده کنی. اما مثلا اگر بدونی نوع اون list از String هست خیلی راحت این کارو میکنی :


    List list = //...
    List<String> stringList = convert(list, new ArrayList<>(), String.class);

  4. #4

    نقل قول: مشکل در کار با لیستها

    احمدجان متد خیلی خوبی نوشت ولی خب جاوا قبلا این رو پیش‌بینی کرده. یه شیء List همواره والد یه <List<String هست و به سادگی بش قابل تبدیله:

    List objectList = Arrays.asList("Tehran", "Mashad", "Esfahan", "Tabriz");
    List<String> stringList = (List<String>)objectList;
    stringList.forEach(System.out::println);

    // Or for clone:
    List<String> copiedList = new ArrayList((List<String>)objectList);

    در مورد ساختمان‌های داده‌ی دیگه مثل LinkedList و TreeSet هم همیشه یه سازنده هست که اون‌رو از روی یه Collection می‌سازه و نیازی به اختراع چرخ از ابتدا نیست:


    TreeSet<String> ts = new TreeSet((List<String>) objectList);
    LinkedList<String> ll = new LinkedList((List<String>) objectList);

    خیلی کم پیش می‌آد که برای تبدیل یا کلون کردن یه ساختمان‌داده مجبور شیم کل اون ساختمان داده رو پیمایش کنیم.
    آخرین ویرایش به وسیله محمد فدوی : سه شنبه 12 اسفند 1393 در 14:50 عصر
    اگر به بهداشت و سلامت حیوانات علاقه دارید، از vetMD.ir دیدن کنید.
    وبلاگ شخصی من: fadavi.net

    اینجا کمتر سر می‌زنم. (تلگرام من)

  5. #5
    کاربر دائمی آواتار ehsan_faal
    تاریخ عضویت
    خرداد 1392
    محل زندگی
    تهران
    پست
    325

    نقل قول: مشکل در کار با لیستها

    آقای فدوی یه سوال داشتم:
    این که گفتید با انتساب یه لیست به یه لیست دیگه در واقع اشاره گر لیست اول تو دومی قرار میگیره در مورد مپ صادق نیست؟
    چون من تست کردم دو تا لیست مختلف رو با key و value یه مپ مقدار دهی کردم و بعد مپ رو پاک کردم، اما لیستها باقی موندند!

  6. #6

    نقل قول: مشکل در کار با لیستها

    در این مورد باید یکم مطالعه کنی. اما بطور کلی در مورد انواع داده‌ای پایه مثل int و double و long... در موقع انتساب مقدار انتقال پیدا می‌کنه. یعنی در اثر اجرای کد زیر:

    int a = 10;
    int b = a;
    a = 5;
    مقدار a به ۵ تغییر می‌کنه ولی مقدار b همچنان ۱۰ می‌مونه. اما در مورد همه‌ی اشیاء بعد از انتساب، مقدار انتقال پیدا نمی‌کنه و فقط اشاره‌گر منتقل می‌شه:

    List<Integer> first = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    List<Integer> second = first;

    در این حالت هردو شیء first و second به یه شیء اشاره می‌کنن. به عبارت دیگه اگه توی first تغییری رخ بده (مثلا عضوی add بشه یا با استفاده از متد clear داده‌های لیست پاک بشن) توی second هم همون تغییر ایجاد می‌شه. اما درصورتی که شما first رو به یه لیست جدید منتسب کنید دیگه از second جدا می‌شه و تغییرات first روی second تاثیر نمی‌ذاره:

    first = Arrays.asList(11, 12, 13, 14, 15);
    second.forEach(System.out::println); // 1 .. 10
    حالا باز با این اوصاف اگه فکر می‌کنی کلاس Map استثنائه کدت رو بذار تا باهم بررسیش کنیم.
    اگر به بهداشت و سلامت حیوانات علاقه دارید، از vetMD.ir دیدن کنید.
    وبلاگ شخصی من: fadavi.net

    اینجا کمتر سر می‌زنم. (تلگرام من)

  7. #7
    کاربر دائمی آواتار ahmad.mo74
    تاریخ عضویت
    مرداد 1393
    محل زندگی
    تهران
    پست
    437

    نقل قول: مشکل در کار با لیستها

    سلام.

    منظور من از clone این بود :


    ArrayList<String> list = new ArrayList<>();
    //...
    ArrayList<String> copyList = (ArrayList<String>) list.clone();


    خودم همیشه از همین روش استفاده میکنم :


    ArrayList<String> list = new ArrayList<>();
    //...
    ArrayList<String> copyList = new ArrayList<>(list);


    قطعا سریع ترین راه هم همینه و متدی که من نوشتم بیشتر زمان میبره ( تقریبا (O(n در مقابل (O(n^2 ).
    اما برای موقعی که نوع لیست مشخص نباشه، من خودم حس خوبی به این قضیه ندارم (چون بعضی مواقع واقعا نوع لیست مشخص نیست) و سعی میکنم امن ترین روش رو براش انتخاب کنم.
    مثلا :


    public static void main(String[] args) {
    List list = Arrays.asList("a", 1, 2.2f);
    List<String> strings = new ArrayList<>(list);
    System.out.println(strings);
    }


    هیچ مشکلی تو کد بالا وجود نداره و حتی اجرا هم میشه! صرفا بخاطر اینکه توی لیست فارغ از نوعش، تمام آیتم ها توی آرایه ای از Object دخیره میشه .
    Object[] elementData

    و متد toString اون آرایه رو چاپ میکنه.
    ولی به محض اینکه توی لیست پیمایش بشه exception رخ میده.

    اما مثلا اگر نوع ورودی با نوعی که مشخص کردیم فرق داشت میتونیم اون رو توی لیست ادد نکنیم :


    @SuppressWarnings("unchecked")
    public static <E, C extends Collection<E>> C convert(Iterable<?> from, C to, Class<E> listClass) {
    for (Object item : from) {
    if (listClass.isInstance(item)) {
    to.add((E) item);
    }
    }
    return to;
    }


    public static void main(String[] args) {
    List list = Arrays.asList("a", "b", 1, 2.2f);
    List<String> strings = convert(list, new ArrayList<>(), String.class);
    System.out.println(strings);
    }


    یا null برگردونیم :


    public static <E, C extends Collection<E>> C convert(Iterable<?> from, C to, Class<E> listClass) {
    try {
    for (Object item : from) {
    to.add(listClass.cast(item));
    }
    } catch (ClassCastException ignored) {
    return null;
    }
    return to;
    }


    یا ... اینطوری میشه جلوی یه سری خطاهای احتمالی رو گرفت. اما در کل اگر از کاری که میکنیم اطمینان داریم بهتره از همون روش اول استفاده بشه.
    آخرین ویرایش به وسیله ahmad.mo74 : دوشنبه 18 اسفند 1393 در 09:30 صبح

  8. #8
    کاربر دائمی آواتار ahmad.mo74
    تاریخ عضویت
    مرداد 1393
    محل زندگی
    تهران
    پست
    437

    نقل قول: مشکل در کار با لیستها

    سلام

    گفتم اینارو در قالب یه کلاس util بنویسم که کارت راحت تر باشه (الگوریتم بهینه تری هم براش نوشتم) :


    import java.util.*;
    import java.util.function.Predicate;


    /**
    * @author avb
    */
    public final class CollectionsUtil {


    public static <E, C extends Collection<E>> C convertTo(Iterable<?> src, C target, Class<E> type) {
    addAllIf(src, target, type::isInstance);
    return target;
    }


    public static <E> List<E> convertToList(Iterable<?> src, Class<E> type) {
    return convertTo(src, new ArrayList<>(), type);
    }


    public static <E> Set<E> convertToSet(Iterable<?> src, Class<E> type) {
    return convertTo(src, new HashSet<>(), type);
    }


    @SuppressWarnings("unchecked")
    public static <E> List<E> copyToList(Iterable<?> src) {
    return new ArrayList<>((Collection<? extends E>) src);
    }


    @SuppressWarnings("unchecked")
    public static <E> Set<E> copyToSet(Iterable<?> src) {
    return new HashSet<>((Collection<? extends E>) src);
    }


    @SuppressWarnings("unchecked")
    public static <E, C extends Collection<E>> void addAllIf(Iterable<?> src, C target, Predicate<Object> predicate) {
    for (Object o : src) {
    if (predicate.test(o)) {
    target.add((E) o);
    }
    }
    }


    }


    براش تست هم نوشتم :


    import java.util.ArrayList;
    import java.util.List;


    /**
    * @author avb
    */
    public class Test {


    static interface Runnable<T> {


    void run(T t);


    }


    static <T> String execute(int iteration, T t, Runnable<T> command) {
    System.out.println("Iteration count = " + iteration);
    long start = System.nanoTime();
    for (int i = 0; i < iteration; i++) {
    command.run(t);
    }
    return "Average execution time : " + (System.nanoTime() - start) / (float) iteration + " ns";
    }


    static List generateList() {
    List list = new ArrayList();
    for (int i = 0; i < 20000; i++) {
    list.add(i);
    }
    for (int i = 20000; i < 40000; i++) {
    list.add(i + .5f);
    }
    for (int i = 40000; i < 60000; i++) {
    list.add(String.valueOf(i));
    }
    System.out.println("Generated list size = " + list.size());
    return list;
    }


    public static void main(String[] args) {
    final int iteration = 10000;
    final List testList = generateList();
    System.out.println("Method : copyToList => " + execute(iteration, testList, CollectionsUtil::copyToList));
    System.out.println("****************************** **********");
    System.out.println("Method : convertTo => " + execute(iteration, testList, list -> CollectionsUtil.convertTo(list, new ArrayList<>(), String.class)));
    System.out.println("****************************** **********");
    System.out.println("Method : convertToList => " + execute(iteration, testList, list -> CollectionsUtil.convertToList(list, String.class)));
    }


    }


    خروجی تست :


    Generated list size = 60000
    Iteration count = 10000
    Method : copyToList => Average execution time : 52340.668 ns
    ****************************************
    Generated list size = 60000
    Iteration count = 10000
    Method : convertTo => Average execution time : 252133.38 ns
    ****************************************
    Generated list size = 60000
    Iteration count = 10000
    Method : convertToList => Average execution time : 220010.7 ns


    پ.ن : این تست برای حالت متوسطه و نتایج بهترین و بدترین حالت میتونه متفاوت باشه (مثلا اگر کل لیست از نوع Integer باشه یا کلش String باشه)
    آخرین ویرایش به وسیله ahmad.mo74 : دوشنبه 18 اسفند 1393 در 09:41 صبح

تاپیک های مشابه

  1. مشکل در کار با quickreport
    نوشته شده توسط شکوفه سلامی در بخش ابزارهای گزارش سازی در دلفی
    پاسخ: 5
    آخرین پست: یک شنبه 05 اسفند 1386, 03:00 صبح
  2. مشکل در کار با ComboBox در SandBar
    نوشته شده توسط omar در بخش VB.NET
    پاسخ: 1
    آخرین پست: سه شنبه 07 مهر 1383, 13:00 عصر
  3. مشکل در کار با sql Server
    نوشته شده توسط شکوفه سلامی در بخش SQL Server
    پاسخ: 2
    آخرین پست: سه شنبه 10 شهریور 1383, 09:23 صبح
  4. مشکل در کار با ado
    نوشته شده توسط در بخش برنامه نویسی در Delphi
    پاسخ: 6
    آخرین پست: پنج شنبه 25 تیر 1383, 14:17 عصر
  5. مشکل در کار با Shell_NotifyIcon
    نوشته شده توسط در بخش برنامه نویسی در Delphi
    پاسخ: 6
    آخرین پست: چهارشنبه 24 تیر 1383, 15:56 عصر

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •