2

Inspired by a question here I was messing around with an experimental Collection:

/**
 * Pretends to be a Collection of samples from the items.
 *
 * @param <T>
 */
class Samples<T> extends AbstractCollection<T[]> implements Collection<T[]> {

    private final int of;
    private final T[] items;

    public Samples(int of, T... items) {
        this.of = of;
        this.items = items;
    }

    @Override
    public int size() {
        // I know this is wrong.
        return items.length * of;
    }

    @Override
    public Iterator<T[]> iterator() {
        // Make the iterator on the fly.
        return new Iterator<T[]>() {
            // Start at the beginning.
            int which = 0;

            @Override
            public boolean hasNext() {
                // That's how many there are.
                return which < size();
            }

            @Override
            public T[] next() {
                // Make my new one by cloning the original.
                T[] next = Arrays.copyOf(items, of);
                // Pick the items with reference to which.
                int count = which;
                for (int i = 0; i < of; i++) {
                    // count mod length is the next one to use.
                    next[i] = items[count % items.length];
                    // Used that now.
                    count /= items.length;
                }
                // Consumed that one.
                which += 1;
                return next;
            }

        };

    }

}

public void test() {
    Samples<String> samples = new Samples(4, "A", "B", "C", "D", "E");
    // Walk it with an iterator.
    Iterator<String[]> i = samples.iterator();
    while (i.hasNext()) {
        System.out.println(Arrays.toString(i.next()));
    }
    // Walk it using enhanced for loop.
    for (String[] s : samples) { // Line 91 - error thrown here.
        System.out.println(Arrays.toString(s));
    }
}

And found that if I pull an iterator out and walk that all works fine but if I try using an enhanced for loop it errors with:

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

Is there something I am missing - perhaps insufficient coffee?

Please ignore the incorrect size method - I am sure it is not the cause of the problem.

PS: jdk = jdk1.8.0_11 but still fails with jdk1.7.0_65

2
  • Where is the exception originating exactly from? Stacktrace? Commented Jul 29, 2014 at 10:36
  • @icza - On the line which reads for (String[] s : samples) {. Commented Jul 29, 2014 at 10:37

1 Answer 1

3

You instantiate a raw type of Samples therefore Samples.items will be of type Object[] not String[] in your case. In your test() method:

Samples<String> samples = new Samples(4, "A", "B", "C", "D", "E");

Change it to:

// Note the diamond operator: <>
Samples<String> samples = new Samples<>(4, "A", "B", "C", "D", "E");

As a side note: In your Samples class you do not need to state you implement Collection because AbstractCollection already does.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.