4

I found the solution to this problem but can't figure out how it works. Can someone please explain this?

public static void main(String[] args) {
Object[] numbers = new Object[100];
Arrays.fill(numbers, new Object() {
    private int count = 0;
    @Override
    public String toString() {
        return Integer.toString(++count);
    }
});
System.out.println(Arrays.toString(numbers));
}

[I could not comment to that answer directly because I dont have enough reputation points.]

5 Answers5

4

Can someone please explain this?

This code is a use of

Arrays.fill(Object[] a, Object val)

Where the Object val provided is an anonymous class with its toString() method overridden.

Arrays.toString(numbers) calls the toString() on the anonymous class for each element in the a array. As the toString() is overridden to increment the count, you get incremented values each time it is called.

However, as @Eran has pointed out, it is not without a loop.

user1717259
  • 2,717
  • 6
  • 30
  • 44
3

To be accurate, Arrays.fill() use a loop in its own implementation. In general, Arrays.fill fills an array by assigning the second parameter to every element of the first parameter (your array).

Your example has an Array of type Object and a length of 100 elements. In Arrays.fill(...) you generate a so-called anonymous class of type Object, which reimplements the toString-method by increasing the value of a counter (int count) and printing it after that.

Now, by calling Arrays.toString the toString() method of every element inside the array is executed (which is the same instance of the anonymous class here), resulting in printing the numbers from 1-100

Force0234
  • 243
  • 3
  • 16
  • 2
    "every Object"? It's actually always the same object and the `toString` method is executed a 100 times on this object. If each cell had it's own instance of Object you would get all 1's. – dingalapadum May 27 '16 at 14:14
  • Yes. Its one object. As per documentation, `Arrays.fill(Object[] a, Object val)` assigns the reference of val to each element of the array `a` – Priyatam Roy May 27 '16 at 14:17
  • 1
    Sorry, you are right. I should have been more accurate here. By saying every Object I meant every Object/Element inside the array. But as I mentioned in the first sentence, it is one instance which gets assigned multiple times. I will edit it to avoid misunderstandings. – Force0234 May 27 '16 at 14:18
  • 1
    Yeah, sorry. I was just being pedantic and I thought it might be good to be very explicit about this detail. I saw you edited your answer +1 – dingalapadum May 27 '16 at 14:23
2
System.out.println(1)
System.out.println(2)
System.out.println(3)
System.out.println(4)
System.out.println(5)
System.out.println(6)
System.out.println(7)
...
System.out.println(100)

:D

To avoid the code-generator proposed by Dmitry, this can be easily done with just copy-paste

int i=0;
System.out.println(++i);
System.out.println(++i);
System.out.println(++i);
System.out.println(++i);
System.out.println(++i);
...
System.out.println(++i);
  • Write the System.out.println(++i) once.
  • Copy and paste 4 times.
  • Then you pick those 5 lines and copy paste them again.
  • You should now have 10 times that line. Select those 10 lines and copy paste another 9 times.
  • done!
dingalapadum
  • 2,077
  • 2
  • 21
  • 31
  • 3
    The only loop is expected to be in the *code generator*, and this loop doesn't count. – Dmitry Bychenko May 27 '16 at 13:51
  • @DmitryBychenko Sorry, I don't quite understand what you are trying to tell me. What code generator are you talking about? And which loop do you mean by "this loop"? – dingalapadum May 27 '16 at 13:54
  • 1
    sorry, just a joke. In order to put down all the lines `System.out.println(1);...System.out.println(100);` you, probably, want a code generator (it's a too tedious task to print out all the lines *manually*) and this generator will have a loop :). Jesting aside, the solution is nice +1 – Dmitry Bychenko May 27 '16 at 13:58
  • @DmitryBychenko updated: my new solution is no so tedious to do by hand ;) – dingalapadum May 27 '16 at 14:08
1

Here is a better solution:

IntStream.rangeClosed(0, 100).forEach(System.out::println);

I think it's self explanatory

Svetlin Zarev
  • 14,713
  • 4
  • 53
  • 82
0

What about this:

public class NoLoopPrint {

    int max;
    int from;

    public NoLoopPrint(int max) {
        this(1, max);
    }

    public NoLoopPrint(int from, int max) {
        this.max = max;
        this.from = from;
    }

    public String toString() {
        if (from >= max) {
            return String.valueOf(max);
        }
        System.out.println(from++);
        return this.toString();
    }

    public static void main(String args[]) {
        System.out.println(new NoLoopPrint(100));
        System.out.println(new NoLoopPrint(10, 20));
    }
}
andy
  • 1,336
  • 9
  • 23