একক যৌক্তিক সংকলনে একাধিক সংগ্রহ একত্রিত করবেন?


110

ধরুন, আমার কাছে ক্লাসের সদস্য হিসাবে ধ্রুব সংখ্যক সংগ্রহ (যেমন 3 অ্যারেলিস্ট) রয়েছে। এখন, আমি অন্যান্য উপাদানগুলিতে সমস্ত উপাদান প্রকাশ করতে চাই যাতে তারা কেবল সমস্ত উপাদানগুলিতে পুনরাবৃত্তি করতে পারে (আদর্শভাবে কেবল পঠনযোগ্য)। আমি পেয়ারা সংগ্রহগুলি ব্যবহার করছি এবং আমি আশ্চর্য হয়েছি যে আমি কীভাবে সাময়িক অনুলিপি তৈরি না করে অভ্যন্তরীণ সংগ্রহগুলিতে যৌক্তিক দৃষ্টিভঙ্গি তৈরির জন্য পেয়ারা পুনরুক্তি / পুনরুক্তি ব্যবহার করতে পারি ।


^^ ভাঙা লিঙ্ক। আমি মনে করি তিনি পেয়ারা
জাভাদোক

উত্তর:


113

পেয়ারার সাহায্যে আপনি এটি ব্যবহার করতে পারেন Iterables.concat(Iterable<T> ...), এটি সমস্ত পুনরাবৃত্তের একটি লাইভ ভিউ তৈরি করে, একটিতে সংমিশ্রিত হয় (যদি আপনি পুনরাবৃত্তগুলি পরিবর্তন করেন তবে সংক্ষিপ্ত সংস্করণটিও পরিবর্তিত হবে)। তারপরে সংক্ষিপ্ত পুনরাবৃত্তিকে মোড়ানো করুন Iterables.unmodifiableIterable(Iterable<T>)(আমি কেবল পঠন- পাঠনের প্রয়োজনীয়তা আগে দেখিনি)।

Iterables.concat( .. )জাভাডক্স থেকে :

একক পুনরাবৃত্তিতে একাধিক পুনরাবৃত্তিকে একত্রিত করে। প্রত্যাবর্তিত পুনরাবৃত্তের একটি পুনরুক্তি রয়েছে যা প্রতিটি পুনরাবৃত্তের ইনপুটগুলির উপাদানগুলি ট্র্যাভার করে। ইনপুট পুনরাবৃত্তিগুলি প্রয়োজনীয় না হওয়া পর্যন্ত পোল করা হয় না। remove() সংশ্লিষ্ট ইনপুট পুনরাবৃত্তিকারীরা এটি সমর্থন করলে প্রত্যাবর্তিত পুনরাবৃত্তের পুনরাবৃত্তি সমর্থন করে।

যদিও এটি সুস্পষ্টভাবে বলতে পারে না যে এটি একটি লাইভ দর্শন, শেষ বাক্যটি বোঝায় যে এটি ( Iterator.remove()পদ্ধতিটিকে সমর্থন করলেই ব্যাকিং ইেটেরেটর সমর্থন করে তবে লাইভ ভিউ ব্যবহার না করা সম্ভব না)

কোডের উদাহরণ:

final List<Integer> first  = Lists.newArrayList(1, 2, 3);
final List<Integer> second = Lists.newArrayList(4, 5, 6);
final List<Integer> third  = Lists.newArrayList(7, 8, 9);
final Iterable<Integer> all =
    Iterables.unmodifiableIterable(
        Iterables.concat(first, second, third));
System.out.println(all);
third.add(9999999);
System.out.println(all);

আউটপুট:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9999999]


সম্পাদনা:

দামিয়ান থেকে অনুরোধ করে, এখানে একটি অনুরূপ পদ্ধতি যা একটি লাইভ সংগ্রহ ভিউ দেয়

public final class CollectionsX {

    static class JoinedCollectionView<E> implements Collection<E> {

        private final Collection<? extends E>[] items;

        public JoinedCollectionView(final Collection<? extends E>[] items) {
            this.items = items;
        }

        @Override
        public boolean addAll(final Collection<? extends E> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void clear() {
            for (final Collection<? extends E> coll : items) {
                coll.clear();
            }
        }

        @Override
        public boolean contains(final Object o) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean containsAll(final Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean isEmpty() {
            return !iterator().hasNext();
        }

        @Override
        public Iterator<E> iterator() {
            return Iterables.concat(items).iterator();
        }

        @Override
        public boolean remove(final Object o) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean removeAll(final Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean retainAll(final Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public int size() {
            int ct = 0;
            for (final Collection<? extends E> coll : items) {
                ct += coll.size();
            }
            return ct;
        }

        @Override
        public Object[] toArray() {
            throw new UnsupportedOperationException();
        }

        @Override
        public <T> T[] toArray(T[] a) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean add(E e) {
            throw new UnsupportedOperationException();
        }

    }

    /**
     * Returns a live aggregated collection view of the collections passed in.
     * <p>
     * All methods except {@link Collection#size()}, {@link Collection#clear()},
     * {@link Collection#isEmpty()} and {@link Iterable#iterator()}
     *  throw {@link UnsupportedOperationException} in the returned Collection.
     * <p>
     * None of the above methods is thread safe (nor would there be an easy way
     * of making them).
     */
    public static <T> Collection<T> combine(
        final Collection<? extends T>... items) {
        return new JoinedCollectionView<T>(items);
    }

    private CollectionsX() {
    }

}

কীভাবে আমি ব্যবহারকারীকে উপাদানগুলি অপসারণ থেকে বাধা দেব? তালিকাগুলি অপরিবর্তনীয় তালিকাতে মোড়ানো ছাড়াও কি সুন্দর উপায় আছে?
newgre

2
@ জেএন_ স্রেফ এটি মুড়ে দিনIterables.unmodifiableIterable(iterable)
সান প্যাট্রিক ফ্লয়েড

2
সংগ্রহ সম্পর্কে কি? Iterables.concatএকটি উত্পাদন করে Iterable, না Collection। আমার একটা Collectionভিউ দরকার
এখনকার

@ ডামিয়ান এর একমাত্র দরকারী বৈশিষ্ট্য হ'ল একত্রিত আকার () পদ্ধতি থাকবে। সংগ্রহ ইন্টারফেসের অন্যান্য সমস্ত পদ্ধতিতে হয় সংজ্ঞায়িত শব্দার্থবিজ্ঞান (অ্যাড ইত্যাদি) বা দুর্বল পারফরম্যান্স (এতে থাকে) থাকবে।
শান প্যাট্রিক ফ্লয়েড

2
@ শিয়ান, হ্যাঁ - size()আমার যা প্রয়োজন তা হল। add()একটি ব্যতিক্রম নিক্ষেপ করা ভাল - আমি এই পদ্ধতির কোনও যত্ন করি না। সংগ্রহের এপিআই ভেঙে গেছে এবং এ সম্পর্কে কেউ কিছুই করতে পারে না। Collection.add(), Iterator.remove()বেলা
এখনকার

101

সাজা জাভা 8 টি সমাধান ব্যবহার করে Stream

ধ্রুব সংখ্যা

ধরে নিচ্ছি private Collection<T> c, c2, c3

একটি সমাধান:

public Stream<T> stream() {
    return Stream.concat(Stream.concat(c.stream(), c2.stream()), c3.stream());
}

আরেকটি সমাধান:

public Stream<T> stream() {
    return Stream.of(c, c2, c3).flatMap(Collection::stream);
}

পরিবর্তনশীল নম্বর

ধরে নেওয়া private Collection<Collection<T>> cs:

public Stream<T> stream() {
    return cs.stream().flatMap(Collection::stream);
}

10

আপনি যদি কমপক্ষে জাভা 8 ব্যবহার করেন তবে আমার অন্য উত্তরটি দেখুন

যদি আপনি ইতিমধ্যে গুগু পেয়ারা ব্যবহার করছেন তবে শন প্যাট্রিক ফ্লয়েডের উত্তর দেখুন

আপনি যদি জাভা at এ আটকে থাকেন এবং গুগল পেয়ারা অন্তর্ভুক্ত করতে না চান, তবে আপনি নিজের লেখার জন্য (কেবল পঠনযোগ্য) এবং এর Iterables.concat()চেয়ে বেশি ব্যবহার না করে লিখতে পারেন :IterableIterator

ধ্রুব সংখ্যা

public static <E> Iterable<E> concat(final Iterable<? extends E> iterable1,
                                     final Iterable<? extends E> iterable2) {
    return new Iterable<E>() {
        @Override
        public Iterator<E> iterator() {
            return new Iterator<E>() {
                final Iterator<? extends E> iterator1 = iterable1.iterator();
                final Iterator<? extends E> iterator2 = iterable2.iterator();

                @Override
                public boolean hasNext() {
                    return iterator1.hasNext() || iterator2.hasNext();
                }

                @Override
                public E next() {
                    return iterator1.hasNext() ? iterator1.next() : iterator2.next();
                }
            };
        }
    };
}

পরিবর্তনশীল নম্বর

@SafeVarargs
public static <E> Iterable<E> concat(final Iterable<? extends E>... iterables) {
    return concat(Arrays.asList(iterables));
}

public static <E> Iterable<E> concat(final Iterable<Iterable<? extends E>> iterables) {
    return new Iterable<E>() {
        final Iterator<Iterable<? extends E>> iterablesIterator = iterables.iterator();

        @Override
        public Iterator<E> iterator() {
            return !iterablesIterator.hasNext() ? Collections.emptyIterator()
                                                : new Iterator<E>() {
                Iterator<? extends E> iterableIterator = nextIterator();

                @Override
                public boolean hasNext() {
                    return iterableIterator.hasNext();
                }

                @Override
                public E next() {
                    final E next = iterableIterator.next();
                    findNext();
                    return next;
                }

                Iterator<? extends E> nextIterator() {
                    return iterablesIterator.next().iterator();
                }

                Iterator<E> findNext() {
                    while (!iterableIterator.hasNext()) {
                        if (!iterablesIterator.hasNext()) {
                            break;
                        }
                        iterableIterator = nextIterator();
                    }
                    return this;
                }
            }.findNext();
        }
    };
}

1

আপনি এটিতে একটি নতুন Listএবং addAll()আপনার অন্যান্য তৈরি Listকরতে পারেন। তারপরে একটি অনিবার্যযোগ্য তালিকাটি ফিরিয়ে দিন Collections.unmodifiableList()


3
এটা একটা নতুন অস্থায়ী সংগ্রহে আছে যা সম্ভাব্য বেশ ব্যয়বহুল তৈরি করবে
newgre

6
ব্যয়বহুল কীভাবে , তালিকাগুলির অন্তর্নিহিত অবজেক্টগুলি অনুলিপি করা হয়নি এবং ArrayListকেবল স্থান এবং কলকে System.arraycopy()হুডের নীচে বরাদ্দ দেয় । এর চেয়ে বেশি দক্ষ হতে পারে না।
কিওয়ারকি

8
প্রতিটি পুনরাবৃত্তির জন্য কীভাবে পুরো সংগ্রহ অনুলিপি করা ব্যয়বহুল নয় ? তদুপরি, আপনি এর থেকে আরও ভাল পেতে পারেন, শ্যানের উত্তর দেখুন।
newgre

এটি মেমরি অনুলিপি করতে একটি দেশীয় বাস্তবায়নও ব্যবহার করে, এটি অ্যারের মাধ্যমে পুনরাবৃত্তি করে না।
কিওয়ারকি

1
আচ্ছা যদি এটি অ্যারে অনুলিপি করে থাকে তবে এটি অবশ্যই একটি ও (এন) অ্যালগরিদম যা স্কেল করে না এবং অ্যারেতে একবারে পুনরায় ঘন হওয়ার মতো জটিলতা রয়েছে। ধরুন যে প্রতিটি তালিকায় এক মিলিয়ন উপাদান রয়েছে, তবে আমাকে কয়েকটি মিলিয়ন উপাদান অনুলিপি করতে হবে, কেবল সেগুলি পুনরুক্ত করার জন্য। খারাপ ধারণা।
newgre

0

এটির জন্য আমার সমাধানটি এখানে:

সম্পাদনা করুন - কোডটি খানিকটা পরিবর্তিত হয়েছে

public static <E> Iterable<E> concat(final Iterable<? extends E> list1, Iterable<? extends E> list2)
{
    return new Iterable<E>()
    {
        public Iterator<E> iterator()
        {
            return new Iterator<E>()
            {
                protected Iterator<? extends E> listIterator = list1.iterator();
                protected Boolean checkedHasNext;
                protected E nextValue;
                private boolean startTheSecond;

                public void theNext()
                {
                    if (listIterator.hasNext())
                    {
                        checkedHasNext = true;
                        nextValue = listIterator.next();
                    }
                    else if (startTheSecond)
                        checkedHasNext = false;
                    else
                    {
                        startTheSecond = true;
                        listIterator = list2.iterator();
                        theNext();
                    }
                }

                public boolean hasNext()
                {
                    if (checkedHasNext == null)
                        theNext();
                    return checkedHasNext;
                }

                public E next()
                {
                    if (!hasNext())
                        throw new NoSuchElementException();
                    checkedHasNext = null;
                    return nextValue;

                }

                public void remove()
                {
                    listIterator.remove();
                }
            };
        }
    };
}

তোমার বাস্তবায়ন ভূমিকা ফ্লিপ hasNext()এবং next()। প্রথমটি আপনার পুনরুক্তির স্থিতি পরিবর্তন করে যখন দ্বিতীয়টি করে না। এটা কাছাকাছি অন্য কোন উপায়ে হওয়া উচিত। কল next()না করে কল hasNext()করলে সবসময় ফল পাওয়া যায় null। কল hasNext()না করে কল করা next()উপাদানগুলিকে ফেলে দেবে। আপনার next()হয় নিক্ষেপ NoSuchElementExceptionনা, পরিবর্তে ফিরে null
xehpuk
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.