2013-04-03 43 views
8

Tôi có một lớp Java có dạng sau:Java Iterator với nhiều loại nguyên thủy

class Example { 

    private byte[][] data; 

    public Example(int s) { data = new byte[s][s]; } 

    public byte getter(int x, int y)   { return byte[x][y]; } 
    public void setter(int x, int y, byte z) { byte[x][y] = z; } 
} 

Tôi muốn để có thể bên ngoài lặp qua các dữ liệu cá nhân sử dụng một iterator như vậy:

for(byte b : Example) { ;/* do stuff */ }

tôi cố gắng thực hiện một lớp Iterator tin nhưng tôi chạy vào vấn đề:

private class ExampleIterator implements Iterator { 
    private int curr_x; 
    private int curr_y; 

    public ExampleIterator() { curr_x=0; curr_y=-1; } 
    public boolean hasNext() { 
    return curr_x != field.length-1 
     && curr_y != field.length-1; //is not the last cell? 
    } 
    public byte next() { // <-- Error is here: 
         // Wants to change return type to Object 
         // Won't compile! 
    if(curr_y=field.length) { ++curr_x; curr_y=0; } 
    return field[curr_x][curr_y]; 
    } 
    public void remove() { ; } //does nothing 
} 

Làm cách nào để triển khai một trình biến đổi bên ngoài cho các loại nguyên thủy (không phải là generics)? Điều này có thể thực hiện được trong Java không?

Trả lời

5

Java 8 giới thiệu primitive iterators, cho phép bạn để tránh boxing/unboxing trong lặp trên int, long và bộ sưu tập đôi.

Bạn có thể tạo riêng cho mình PrimitiveIterator trong số byte với việc triển khai các loại PrimitiveIterator<Byte,ByteConsumer> chung chung. ByteConsumer cũng sẽ được thực hiện. Cả hai đều khá đơn giản.

Tại sao không có PrimitiveIterator.ofByte trong jdk? Có lẽ vì kích thước từ máy, thường không nhỏ hơn int. Hoặc các trình vòng lặp byte được thực hiện tốt hơn bằng các luồng và như vậy.

+0

Có tương tự 'Iterable' cho các kiểu nguyên thủy, vì vậy tôi có thể thực hiện' for (double d: myContainerWithDoubles) {} '? –

+0

Không có trình lặp vòng lặp nguyên gốc. Phù hợp nhất là triển khai 'PrimitiveIterator.OfDouble' và sử dụng nó theo kiểu chức năng. – Oroboros102

8

Trình lặp không thể mang lại giá trị của một kiểu nguyên thủy. Tuy nhiên, nó có thể mang lại giá trị của loại bao bọc Byte. Các giá trị như vậy có thể là auto-unboxed thành byte (miễn là chúng không phải là null).

private class ExampleIterator implements Iterator<Byte> { 
    public boolean hasNext() { ... } 
    public Byte next() { ... } 
} 

Sau đó, bạn có thể sử dụng nó như vậy:

for (byte b : example) { ... } 
+0

Tôi không quen với khái niệm về quyền tự động (un) boxing. Đây là nơi mà sự nhầm lẫn của tôi bắt nguồn từ và nơi mà các giải pháp đã được tìm thấy. –

+0

@awashburn: Xem http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html – NPE

+2

Thông thường autoboxing như thế này là một cách để tạo ra rất nhiều rác nhanh chóng.Tuy nhiên, đối với 'Byte', tôi tin rằng hầu hết các triển khai Java sử dụng một mẫu flyweight (vì chỉ có 256' byte' giá trị), do đó, không có thêm gánh nặng cho GC. Lưu ý, tuy nhiên, bạn phải sử dụng 'for (byte b: instanceOfExample)' - bạn không thể lặp qua một lớp. –

0

Thực hiện Iterable, và trả về một đối tượng Byte thay vì một byte nguyên thủy:

class Example implements Iterable<Byte> { 

.. 

    public Iterator<Byte> iterator() { 
     return new MyIterator(); 
    } 

    private class MyIterator implements Iterator<Byte> { 
     public Byte next() {...} 
     .... 
    } 
} 

thực hiện Iterable thay vì Iterator cho phép bạn để lặp lại trực tiếp các mục đối tượng, sử dụng vòng lặp for-each.

1

Bạn không thể sử dụng Generics với nguyên thủy, vì Generics yêu cầu một lớp cho loại.

Những gì bạn có thể làm là lặp qua các loại Wrapper (Integer, Byte, Boolean, vv) ...

0

Nếu bạn muốn iterator của bạn để thực hiện java.util.Iterator sau đó tiếp theo() sẽ phải trả lại Byte

class ByteArrayIterator implements Iterator<Byte> { 
    final byte[] a; 
    int i = 0; 
    ByteArrayIterator(byte[] a) { 
     this.a = a; 
    } 

    public boolean hasNext() { 
     return i < a.length; 
    } 

    public Byte next() { 
     if (i == a.length) { 
      throw new NoSuchElementException(); 
     } 
     return a[i++]; 
    } 

    public void remove() { 
     throw new UnsupportedOperationException(); 
    } 
} 

xóa cũng có thể được thực hiện. Nếu bạn không cần nó Iterator implemnent sau đó chúng ta có thể thay đổi tiếp theo() để trở về byte

class ByteArrayIterator { 
... 
    public byte next() { 
      if (i == a.length) { 
       throw new NoSuchElementException(); 
      } 
      return a[i++]; 
     } 
Các vấn đề liên quan