原始类型的Java迭代器

时间:2013-04-03 15:11:17

标签: java iterator primitive private-members autoboxing

我有一个以下形式的Java类:

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;    }
}

我希望能够使用像这样的迭代器外部迭代私有数据:

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

我试图实现一个私有的Iterator类,但我遇到了问题:

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
}

如何为原始类型(非泛型)实现外部迭代器?这在Java中是否可行?

5 个答案:

答案 0 :(得分:8)

迭代器无法生成基本类型的值。但是,它可以产生包装类型Byte的值。这些值可以是auto-unboxedbyte(只要它们不是null)。

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

然后你可以像这样使用它:

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

答案 1 :(得分:6)

Java 8引入了primitive iterators,允许您在int,long和double集合的迭代过程中避免装箱/取消装箱。

您可以使用类型安全地实现通用PrimitiveIterator来创建byte PrimitiveIterator<Byte,ByteConsumer>ByteConsumerPrimitiveIterator.ofByte也将被实施。两者都非常简单。

为什么jdk中没有#define _WIN32_IE 0x0501 #define _WIN32_WINNT 0x0501 #define WINVER 0x0510 #include <windows.h> #include <commctrl.h> #include <stdio.h> #include "resource.h" #include <dwmapi.h> #include <gdiplus.h> #include <wingdi.h> using namespace Gdiplus; HINSTANCE hInst; // BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF HBITMAP mLoadImageFile(wchar_t *filename) { HBITMAP result = NULL; Bitmap bitmap(filename, false); Color colBkg(0,0,0,0); bitmap.GetHBITMAP(colBkg, &result); return result; } HBITMAP zCreateDibSection(HDC hdc, int width, int height, int bitCount) { BITMAPINFO bi; ZeroMemory(&bi, sizeof(bi)); bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = width; bi.bmiHeader.biHeight = height; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = bitCount; bi.bmiHeader.biCompression = BI_RGB; return CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, 0,0,0); } HRESULT ExtendGlassIntoClient(HWND hwnd, int left, int right, int top, int bottom) { MARGINS margins = {left,right,top,bottom}; HRESULT hr = S_OK; hr = DwmExtendFrameIntoClientArea(hwnd,&margins); if (SUCCEEDED(hr)) { // ... } return hr; } HBITMAP mImg, mStackOverflowBitmap; HDC memDC, memDC2; HBITMAP oldBmp, oldBmp2; LRESULT CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_INITDIALOG: { ExtendGlassIntoClient(hwndDlg, 0,0,50,0); mImg = mLoadImageFile(L"girl.png"); mStackOverflowBitmap = zCreateDibSection(NULL, 200, 50, 32); memDC = CreateCompatibleDC(NULL); memDC2 = CreateCompatibleDC(NULL); oldBmp = (HBITMAP)SelectObject(memDC, mImg); oldBmp2 = (HBITMAP)SelectObject(memDC2, mStackOverflowBitmap); // ** DOESNT WORK ** - produces a washed-out pink rectangle ***** // HBRUSH mBrush = CreateSolidBrush( RGB(128,0,255) ); // RECT mRect = {0,0,200,50}; // FillRect(memDC2, &mRect, mBrush); // DeleteObject(mBrush); Color mCol(255,128,0,255); SolidBrush mBrush(mCol); Graphics graphics(memDC2); graphics.FillRectangle(&mBrush, (int)0, (int)0, 200, 50); } return TRUE; case WM_ERASEBKGND: { HDC hdc; RECT mRect, topRect; hdc = (HDC)wParam; GetClientRect(hwndDlg, &mRect); topRect = mRect; topRect.bottom = 50; FillRect(hdc, &topRect, (HBRUSH)GetStockObject(BLACK_BRUSH)); mRect.top += 50; FillRect(hdc, &mRect, (HBRUSH)GetStockObject(WHITE_BRUSH)); BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; AlphaBlend(hdc, 0,0, 55,96, memDC, 0, 0, 55,96, bf); AlphaBlend(hdc, 100,32,200,50, memDC2, 0,0,200,50, bf); return 1; } case WM_CLOSE: { EndDialog(hwndDlg, 0); } return TRUE; case WM_COMMAND: { switch(LOWORD(wParam)) { } } return TRUE; } return FALSE; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); hInst=hInstance; InitCommonControls(); int retVal = DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain); GdiplusShutdown(gdiplusToken); return retVal; } ?可能是因为机器字大小,通常不小于int。或者字节迭代器最好由流等完成。

答案 2 :(得分:1)

您不能将泛型与基元一起使用,因为泛型需要类型的类。

你可以做的是迭代Wrapper类型(整数,字节,布尔等)......

答案 3 :(得分:0)

实现Iterable,并返回Byte对象而不是字节原语:

class Example implements Iterable<Byte> {

..

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

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

实现Iterable而不是Iterator允许您使用for-each循环直接循环对象项。

答案 4 :(得分:0)

如果您希望迭代器实现java.util.Iterator,那么next()必须返回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();
    }
}

删除也可以实现。如果你不需要它实现Iterator,那么我们可以改变next()来返回字节

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