您的位置:首页 > 编程语言 > Java开发

jdk源码阅读之 java.util.Iterator

2016-12-18 21:52 423 查看

作用

Itarator
是一个泛型接口,主要描述遍历的手段, 需要实现两个方法
hasNext
,
next


hasNext
方法 返回一个
boolean
用来描述是否还有下一个

next
方法 用来返回下一个值

iterator
的使用方式应该总是先用
hasNext
来判断是否有更多的内容, 然后再用
next
来获取下一条数据

使用

通过实现一个数据库表记录迭代器
TableDataIterator
来加强印象

实现要求

约定:

表必须包含名为
id
的列

id必须为自增整数

通过传入表名后能够将整张表的数据都遍历出来

实现

import java.sql.*;
import java.util.*;

/**
* Created by 0x0001 on 16/12/18.
*/
public class TableDataIterator implements Iterator<Map<String, Object>> {

// 表名
private final String tableName;
// 缓存数据条数
private final int bufSize = 20;

// 上一次最后一条记录的ID
private int prevID = 0;

private final List<Map<String, Object>> buffers;

static {
// 加载数据库驱动
try {
Class.forName("driver class full name");
} catch(Exception e) {
throw new RuntimeException(e);
}
}

public TableDataIterator(String tableName) {
this.tableName = tableName;
buffers = new ArrayList<>();
}

@Override
public boolean hasNext() {
// 如果缓存不为空则允许迭代, 否则尝试加载数据到缓存
return !buffers.isEmpty() || loadToCache();
}

@Override
public Map<String, Object> next() {
if (hasNext()) {
return buffers.remove(0);
}
throw new IllegalStateException("no more data");
}

private boolean loadToCache() {

String sql = "SELECT * FROM " + tableName + " WHERE id > ? ORDER BY id ASC LIMIT ?";

try (Connection conn = getConnection()) {
try(PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setObject(1, prevID);
pstmt.setObject(2, bufSize);

try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
buffers.add(rs2Map(rs));
}

// 数据加载到buf以后顺便设置当前已经获取到的数据的最后一条的id
if (!buffers.isEmpty()) {
Map<String, Object> last = buffers.get(buffers.size() -1);
prevID = (Integer) last.get("id");
}
}
}

} catch(SQLException e) {
throw new RuntimeException(e);
}

return !buffers.isEmpty();
}

private Connection getConnection() {
try {
return DriverManager.getConnection("jdbc_url");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}

private Map<String, Object> rs2Map(ResultSet rs) {
try {
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();

Map<String, Object> row = new HashMap<String, Object>();

for (int i = 0; i < columnCount; i++) {
String name = metaData.getColumnName(i);
Object data = rs.getObject(i);
row.put(name, data);
}

return row;

} catch (SQLException e) {
throw new RuntimeException(e);
}
}

public static void main(String[] args) {
Iterator<Map<String, Object>> iterator = new TableDataIterator("user");
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}

配合
Iterable
能实现一个可以使用
for-each
循环的迭代器, 如:

class TableDataIterable implements Iterable<Map<String, Object>> {
private final String tableName;
TableDataIterable(String tableName) {
this.tableName = tableName;
}

@Override
public Iterator<Map<String, Object>> iterator() {
return new TableDataIterator(tableName);
}

public static void main(String[] args) {
for(Map<String, Object> row : new TableDataIterable("user")) {
System.out.println(row);
}
}
}

使用起来将更加方便,
for-each
循环被jdk编译后代码应该大致如下:

Iterator<Map<String, Object>> iterator = new TableDataIterable("user").iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: