mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-12-08 18:18:38 +08:00
ArrangementTest
This commit is contained in:
parent
bad0c4c982
commit
6cbdf89fe6
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package cn.hutool.v7.core.math;
|
package cn.hutool.v7.core.math;
|
||||||
|
|
||||||
import cn.hutool.v7.core.array.ArrayUtil;
|
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -74,7 +72,7 @@ public class Arrangement implements Serializable {
|
|||||||
long result = 1;
|
long result = 1;
|
||||||
// 从 n 到 n-m+1 逐个乘
|
// 从 n 到 n-m+1 逐个乘
|
||||||
for (int i = 0; i < m; i++) {
|
for (int i = 0; i < m; i++) {
|
||||||
long next = result * (n - i);
|
final long next = result * (n - i);
|
||||||
// 溢出检测
|
// 溢出检测
|
||||||
if (next < result) {
|
if (next < result) {
|
||||||
throw new ArithmeticException("Overflow computing A(" + n + "," + m + ")");
|
throw new ArithmeticException("Overflow computing A(" + n + "," + m + ")");
|
||||||
@ -149,11 +147,11 @@ public class Arrangement implements Serializable {
|
|||||||
return Collections.singletonList(new String[0]);
|
return Collections.singletonList(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
long estimated = count(datas.length, m);
|
final long estimated = count(datas.length, m);
|
||||||
int capacity = estimated > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) estimated;
|
final int capacity = estimated > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) estimated;
|
||||||
|
|
||||||
List<String[]> result = new ArrayList<>(capacity);
|
final List<String[]> result = new ArrayList<>(capacity);
|
||||||
boolean[] visited = new boolean[datas.length];
|
final boolean[] visited = new boolean[datas.length];
|
||||||
dfs(new String[m], 0, visited, result);
|
dfs(new String[m], 0, visited, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -194,7 +192,7 @@ public class Arrangement implements Serializable {
|
|||||||
* @param m 选择的元素个数
|
* @param m 选择的元素个数
|
||||||
* @return 排列迭代器
|
* @return 排列迭代器
|
||||||
*/
|
*/
|
||||||
public Iterable<String[]> iterate(int m) {
|
public Iterable<String[]> iterate(final int m) {
|
||||||
return () -> new ArrangementIterator(datas, m);
|
return () -> new ArrangementIterator(datas, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,10 +206,18 @@ public class Arrangement implements Serializable {
|
|||||||
|
|
||||||
private final String[] datas;
|
private final String[] datas;
|
||||||
private final int m;
|
private final int m;
|
||||||
|
private final int n;
|
||||||
private final boolean[] visited;
|
private final boolean[] visited;
|
||||||
private final String[] buffer;
|
private final String[] buffer;
|
||||||
private final Deque<Integer> stack = new ArrayDeque<>();
|
|
||||||
boolean end = false;
|
// 每一层记录当前尝试的下标,-1表示还未尝试
|
||||||
|
private final int[] indices;
|
||||||
|
private int depth;
|
||||||
|
private boolean end;
|
||||||
|
|
||||||
|
// 预取下一个元素
|
||||||
|
private String[] nextItem;
|
||||||
|
private boolean nextPrepared;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造函数
|
* 构造函数
|
||||||
@ -219,62 +225,137 @@ public class Arrangement implements Serializable {
|
|||||||
* @param datas 数据数组
|
* @param datas 数据数组
|
||||||
* @param m 选择的元素个数
|
* @param m 选择的元素个数
|
||||||
*/
|
*/
|
||||||
ArrangementIterator(String[] datas, int m) {
|
ArrangementIterator(final String[] datas, final int m) {
|
||||||
this.datas = datas;
|
this.datas = datas;
|
||||||
this.m = m;
|
this.m = m;
|
||||||
this.visited = new boolean[datas.length];
|
this.n = datas.length;
|
||||||
this.buffer = new String[m];
|
this.visited = new boolean[n];
|
||||||
// 初始化 dfs 栈
|
this.nextItem = null;
|
||||||
stack.push(0);
|
this.nextPrepared = false;
|
||||||
|
|
||||||
|
if (m < 0 || m > n) {
|
||||||
|
// 无效或无解,直接结束
|
||||||
|
this.indices = new int[Math.max(1, m)];
|
||||||
|
this.buffer = new String[Math.max(1, m)];
|
||||||
|
this.depth = -1;
|
||||||
|
this.end = true;
|
||||||
|
} else if (m == 0) {
|
||||||
|
// m == 0: 只返回一个空数组
|
||||||
|
this.indices = new int[0];
|
||||||
|
this.buffer = new String[0];
|
||||||
|
this.depth = 0;
|
||||||
|
this.end = false;
|
||||||
|
} else {
|
||||||
|
this.indices = new int[m];
|
||||||
|
Arrays.fill(this.indices, -1);
|
||||||
|
this.buffer = new String[m];
|
||||||
|
this.depth = 0;
|
||||||
|
this.end = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return !end;
|
if (end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (nextPrepared) {
|
||||||
|
return nextItem != null;
|
||||||
|
}
|
||||||
|
prepareNext();
|
||||||
|
return nextItem != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] next() {
|
public String[] next() {
|
||||||
while (!stack.isEmpty()) {
|
if (end && !nextPrepared) {
|
||||||
int depth = stack.size() - 1;
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
if (!nextPrepared) {
|
||||||
|
prepareNext();
|
||||||
|
}
|
||||||
|
if (nextItem == null) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
final String[] ret = nextItem;
|
||||||
|
// 清除预取缓存,下一次需要重新准备
|
||||||
|
nextItem = null;
|
||||||
|
nextPrepared = false;
|
||||||
|
// 如果m == 0,该项是唯一项,迭代结束
|
||||||
|
if (m == 0) {
|
||||||
|
end = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int idx = stack.pop();
|
/**
|
||||||
if (idx >= datas.length) {
|
* 将状态推进到下一个可返回的排列并把它放入 nextItem。
|
||||||
// 这一层遍历结束
|
* 如果无更多排列,则将 end=true 并把 nextItem 置为 null。
|
||||||
if (!stack.isEmpty()) {
|
*/
|
||||||
int prev = stack.pop();
|
private void prepareNext() {
|
||||||
stack.push(prev + 1);
|
// 已经准备过或已结束
|
||||||
|
if (nextPrepared || end) {
|
||||||
|
nextPrepared = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// special-case m == 0
|
||||||
|
if (m == 0) {
|
||||||
|
nextItem = new String[0];
|
||||||
|
nextPrepared = true;
|
||||||
|
// do not set end here; end will be set after returning this element in next()
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非递归模拟DFS,直到找到一个可返回的排列或穷尽
|
||||||
|
while (depth >= 0) {
|
||||||
|
final int start = indices[depth] + 1;
|
||||||
|
boolean found = false;
|
||||||
|
for (int i = start; i < n; i++) {
|
||||||
|
if (!visited[i]) {
|
||||||
|
// 如果当前层之前有选过一个元素,要先取消之前选中的 visited
|
||||||
|
if (indices[depth] != -1) {
|
||||||
|
visited[indices[depth]] = false;
|
||||||
|
}
|
||||||
|
indices[depth] = i;
|
||||||
|
visited[i] = true;
|
||||||
|
buffer[depth] = datas[i];
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
// 本层没有可用元素,回溯
|
||||||
|
if (indices[depth] != -1) {
|
||||||
|
visited[indices[depth]] = false;
|
||||||
|
indices[depth] = -1;
|
||||||
|
}
|
||||||
|
depth--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果该元素未使用
|
// 若已达到输出深度,准备输出(但不抛出)
|
||||||
if (!visited[idx]) {
|
if (depth == m - 1) {
|
||||||
visited[idx] = true;
|
nextItem = Arrays.copyOf(buffer, m);
|
||||||
buffer[depth] = datas[idx];
|
// 取消当前visited,为下一次在同一层寻找下一个候选做准备
|
||||||
|
visited[indices[depth]] = false;
|
||||||
if (depth == m - 1) {
|
// 保持 depth 不变(下一次 prepare 会从 indices[depth]+1 开始寻找)
|
||||||
// 输出一个排列
|
nextPrepared = true;
|
||||||
visited[idx] = false;
|
return;
|
||||||
|
} else {
|
||||||
// 下一次从 idx+1 继续
|
// 向下一层深入:初始化下一层为-1并继续循环
|
||||||
stack.push(idx + 1);
|
depth++;
|
||||||
|
if (depth < m) {
|
||||||
return Arrays.copyOf(buffer, m);
|
indices[depth] = -1;
|
||||||
} else {
|
|
||||||
// 继续下一层
|
|
||||||
stack.push(idx + 1); // 当前层下一个起点
|
|
||||||
stack.push(0); // 下一层起点
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 已访问则跳过
|
|
||||||
stack.push(idx + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 若循环结束,说明已经穷尽所有可能
|
||||||
end = true;
|
end = true;
|
||||||
return null;
|
nextItem = null;
|
||||||
|
nextPrepared = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +367,7 @@ public class Arrangement implements Serializable {
|
|||||||
* @param visited 标记数组,记录哪些索引已经被使用了
|
* @param visited 标记数组,记录哪些索引已经被使用了
|
||||||
* @param result 结果集
|
* @param result 结果集
|
||||||
*/
|
*/
|
||||||
private void dfs(String[] current, int depth, boolean[] visited, List<String[]> result) {
|
private void dfs(final String[] current, final int depth, final boolean[] visited, final List<String[]> result) {
|
||||||
if (depth == current.length) {
|
if (depth == current.length) {
|
||||||
result.add(Arrays.copyOf(current, current.length));
|
result.add(Arrays.copyOf(current, current.length));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import cn.hutool.v7.core.lang.Console;
|
|||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
@ -152,4 +153,51 @@ public class ArrangementTest {
|
|||||||
assertArrayEquals(new String[]{"1", "2"}, all.get(3));
|
assertArrayEquals(new String[]{"1", "2"}, all.get(3));
|
||||||
assertArrayEquals(new String[]{"1", "2", "3"}, all.get(9));
|
assertArrayEquals(new String[]{"1", "2", "3"}, all.get(9));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// 迭代器测试
|
||||||
|
// ----------------------------------------------------
|
||||||
|
@Test
|
||||||
|
public void iteratorTest() {
|
||||||
|
final Arrangement arrangement = new Arrangement(new String[]{"1", "2", "3"});
|
||||||
|
|
||||||
|
// 测试 m=2 的情况
|
||||||
|
final List<String[]> iterResult = new ArrayList<>();
|
||||||
|
for (final String[] perm : arrangement.iterate(2)) {
|
||||||
|
iterResult.add(perm);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(6, iterResult.size());
|
||||||
|
assertArrayEquals(new String[]{"1", "2"}, iterResult.get(0));
|
||||||
|
assertArrayEquals(new String[]{"1", "3"}, iterResult.get(1));
|
||||||
|
assertArrayEquals(new String[]{"2", "1"}, iterResult.get(2));
|
||||||
|
assertArrayEquals(new String[]{"2", "3"}, iterResult.get(3));
|
||||||
|
assertArrayEquals(new String[]{"3", "1"}, iterResult.get(4));
|
||||||
|
assertArrayEquals(new String[]{"3", "2"}, iterResult.get(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iteratorFullTest() {
|
||||||
|
final Arrangement arrangement = new Arrangement(new String[]{"1", "2", "3"});
|
||||||
|
|
||||||
|
// 测试全排列的情况
|
||||||
|
final List<String[]> iterResult = new ArrayList<>();
|
||||||
|
for (final String[] perm : arrangement.iterate(3)) {
|
||||||
|
iterResult.add(perm);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(6, iterResult.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iteratorBoundaryTest() {
|
||||||
|
final Arrangement arrangement = new Arrangement(new String[]{"1", "2", "3"});
|
||||||
|
|
||||||
|
// 测试 m > n 的情况
|
||||||
|
final List<String[]> iterResult = new ArrayList<>();
|
||||||
|
for (final String[] perm : arrangement.iterate(5)) {
|
||||||
|
iterResult.add(perm);
|
||||||
|
}
|
||||||
|
assertTrue(iterResult.isEmpty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -133,7 +133,7 @@ public class Excel03SaxReader implements HSSFListener, ExcelSaxReader<Excel03Sax
|
|||||||
* @throws POIException IO异常包装
|
* @throws POIException IO异常包装
|
||||||
*/
|
*/
|
||||||
public Excel03SaxReader read(final POIFSFileSystem fs, final String idOrRidOrSheetName) throws POIException {
|
public Excel03SaxReader read(final POIFSFileSystem fs, final String idOrRidOrSheetName) throws POIException {
|
||||||
this.sheetIndex = getSheetIndex(idOrRidOrSheetName);
|
initSheetIndexOrSheetName(idOrRidOrSheetName);
|
||||||
|
|
||||||
formatListener = new FormatTrackingHSSFListener(new MissingRecordAwareHSSFListener(this));
|
formatListener = new FormatTrackingHSSFListener(new MissingRecordAwareHSSFListener(this));
|
||||||
final HSSFRequest request = new HSSFRequest();
|
final HSSFRequest request = new HSSFRequest();
|
||||||
@ -373,33 +373,33 @@ public class Excel03SaxReader implements HSSFListener, ExcelSaxReader<Excel03Sax
|
|||||||
/**
|
/**
|
||||||
* 获取sheet索引,从0开始
|
* 获取sheet索引,从0开始
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Excel03中没有rid概念,如果传入'rId'开头,直接去除rId前缀,按照sheetIndex对待</li>
|
* <li>Excel03中没有rid概念,如果传入'rId'开头,rid从1开始计数,直接去除rId前缀并减1,转换为sheetIndex</li>
|
||||||
* <li>传入纯数字,表示sheetIndex</li>
|
* <li>传入纯数字,表示sheetIndex</li>
|
||||||
|
* <li>传入sheet名称,例如'sheet1',则读取sheetName,sheetIndex使用-1表示。</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,从0开始,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet
|
* @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,从0开始,rid必须加rId前缀,例如rId1,从1开始,如果为-1处理所有编号的sheet
|
||||||
* @return sheet索引,从0开始
|
|
||||||
* @since 5.5.5
|
* @since 5.5.5
|
||||||
*/
|
*/
|
||||||
private int getSheetIndex(final String idOrRidOrSheetName) {
|
private void initSheetIndexOrSheetName(final String idOrRidOrSheetName) {
|
||||||
Assert.notBlank(idOrRidOrSheetName, "id or rid or sheetName must be not blank!");
|
Assert.notBlank(idOrRidOrSheetName, "id or rid or sheetName must be not blank!");
|
||||||
|
|
||||||
// rid直接处理
|
// rid直接处理
|
||||||
if (StrUtil.startWithIgnoreCase(idOrRidOrSheetName, RID_PREFIX)) {
|
if (StrUtil.startWithIgnoreCase(idOrRidOrSheetName, RID_PREFIX)) {
|
||||||
return Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRidOrSheetName, RID_PREFIX));
|
// rid从1开始计数,此处转换为从0开始的索引
|
||||||
|
this.sheetIndex = Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRidOrSheetName, RID_PREFIX)) - 1;
|
||||||
} else if(StrUtil.startWithIgnoreCase(idOrRidOrSheetName, SHEET_NAME_PREFIX)){
|
} else if(StrUtil.startWithIgnoreCase(idOrRidOrSheetName, SHEET_NAME_PREFIX)){
|
||||||
// since 5.7.10,支持任意名称
|
// since 5.7.10,支持任意名称
|
||||||
this.sheetName = StrUtil.removePrefixIgnoreCase(idOrRidOrSheetName, SHEET_NAME_PREFIX);
|
this.sheetName = StrUtil.removePrefixIgnoreCase(idOrRidOrSheetName, SHEET_NAME_PREFIX);
|
||||||
} else {
|
} else {
|
||||||
|
// 传入纯数字,表示sheetIndex
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(idOrRidOrSheetName);
|
this.sheetIndex = Integer.parseInt(idOrRidOrSheetName);
|
||||||
} catch (final NumberFormatException ignore) {
|
} catch (final NumberFormatException ignore) {
|
||||||
// 如果用于传入非数字,按照sheet名称对待
|
// 如果用于传入非数字,按照sheet名称对待
|
||||||
this.sheetName = idOrRidOrSheetName;
|
this.sheetName = idOrRidOrSheetName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
// ---------------------------------------------------------------------------------------------- Private method end
|
// ---------------------------------------------------------------------------------------------- Private method end
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,9 +24,9 @@ import java.io.InputStream;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sax方式读取Excel接口,提供一些共用方法
|
* Sax方式读取Excel接口,提供一些共用方法
|
||||||
* @author Looly
|
|
||||||
*
|
*
|
||||||
* @param <T> 子对象类型,用于标记返回值this
|
* @param <T> 子对象类型,用于标记返回值this
|
||||||
|
* @author Looly
|
||||||
* @since 3.2.0
|
* @since 3.2.0
|
||||||
*/
|
*/
|
||||||
public interface ExcelSaxReader<T> {
|
public interface ExcelSaxReader<T> {
|
||||||
@ -41,29 +41,41 @@ public interface ExcelSaxReader<T> {
|
|||||||
String SHEET_NAME_PREFIX = "sheetName:";
|
String SHEET_NAME_PREFIX = "sheetName:";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel
|
* 开始从文件中读取Excel
|
||||||
*
|
*
|
||||||
* @param file Excel文件
|
* @param file Excel文件
|
||||||
* @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet
|
* @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,规则如下:
|
||||||
|
* <ul>
|
||||||
|
* <li>如果为-1,处理所有编号的sheet</li>
|
||||||
|
* <li>如果为rId开头,例如rId1,表示读取指定编号的sheet,从1计数,即rId1表示第一个sheet</li>
|
||||||
|
* <li>如果为sheet名称,例如sheet1,直接读取名车给对应sheet</li>
|
||||||
|
* <li>如果为纯数字,在03中表示index,从0开始,07中表示sheet id,从1开始</li>
|
||||||
|
* </ul>
|
||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
T read(File file, String idOrRidOrSheetName) throws POIException;
|
T read(File file, String idOrRidOrSheetName) throws POIException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel,读取结束后并不关闭流
|
* 开始从流中读取Excel,读取结束后并不关闭流
|
||||||
*
|
*
|
||||||
* @param in Excel流
|
* @param in Excel流
|
||||||
* @param idOrRidOrSheetName Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet
|
* @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,规则如下:
|
||||||
|
* <ul>
|
||||||
|
* <li>如果为-1,处理所有编号的sheet</li>
|
||||||
|
* <li>如果为rId开头,例如rId1,表示读取指定编号的sheet,从1计数,即rId1表示第一个sheet</li>
|
||||||
|
* <li>如果为sheet名称,例如sheet1,直接读取名车给对应sheet</li>
|
||||||
|
* <li>如果为纯数字,在03中表示index,从0开始,07中表示sheet id,从1开始</li>
|
||||||
|
* </ul>
|
||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
T read(InputStream in, String idOrRidOrSheetName) throws POIException;
|
T read(InputStream in, String idOrRidOrSheetName) throws POIException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel,读取所有sheet
|
* 开始从路径中读取Excel,读取所有sheet
|
||||||
*
|
*
|
||||||
* @param path Excel文件路径
|
* @param path Excel文件路径,如果是相对路径,则相对classpath
|
||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
@ -72,7 +84,7 @@ public interface ExcelSaxReader<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel,读取所有sheet
|
* 开始从文件中读取Excel,读取所有sheet
|
||||||
*
|
*
|
||||||
* @param file Excel文件
|
* @param file Excel文件
|
||||||
* @return this
|
* @return this
|
||||||
@ -83,7 +95,7 @@ public interface ExcelSaxReader<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel,读取所有sheet,读取结束后并不关闭流
|
* 开始从流中读取Excel,读取所有sheet,读取结束后并不关闭流
|
||||||
*
|
*
|
||||||
* @param in Excel包流
|
* @param in Excel包流
|
||||||
* @return this
|
* @return this
|
||||||
@ -94,22 +106,28 @@ public interface ExcelSaxReader<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel
|
* 开始从路径中读取Excel
|
||||||
*
|
*
|
||||||
* @param path 文件路径
|
* @param path 文件路径,如果是相对路径,则相对classpath
|
||||||
* @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet
|
* @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet
|
||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
default T read(final String path, final int idOrRidOrSheetName) throws POIException {
|
default T read(final String path, final int idOrRid) throws POIException {
|
||||||
return read(FileUtil.file(path), idOrRidOrSheetName);
|
return read(FileUtil.file(path), idOrRid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel
|
* 开始读取Excel
|
||||||
*
|
*
|
||||||
* @param path 文件路径
|
* @param path 文件路径
|
||||||
* @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet
|
* @param idOrRidOrSheetName Excel中的sheet id或者rid编号或sheet名称,规则如下:
|
||||||
|
* <ul>
|
||||||
|
* <li>如果为-1,处理所有编号的sheet</li>
|
||||||
|
* <li>如果为rId开头,例如rId1,表示读取指定编号的sheet,从1计数,即rId1表示第一个sheet</li>
|
||||||
|
* <li>如果为sheet名称,例如sheet1,直接读取名车给对应sheet</li>
|
||||||
|
* <li>如果为纯数字,在03中表示index,从0开始,07中表示sheet id,从1开始</li>
|
||||||
|
* </ul>
|
||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
@ -118,26 +136,34 @@ public interface ExcelSaxReader<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel
|
* 开始从文件中读取Excel
|
||||||
*
|
*
|
||||||
* @param file Excel文件
|
* @param file Excel文件
|
||||||
* @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet
|
* @param idOrRid Excel中的sheet id或者rid编号,规则如下:
|
||||||
|
* <ul>
|
||||||
|
* <li>如果为-1,处理所有编号的sheet</li>
|
||||||
|
* <li>如果为纯数字,在03中表示index,从0开始,07中表示sheet id,从1开始</li>
|
||||||
|
* </ul>
|
||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
default T read(final File file, final int rid) throws POIException{
|
default T read(final File file, final int idOrRid) throws POIException {
|
||||||
return read(file, String.valueOf(rid));
|
return read(file, String.valueOf(idOrRid));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel,读取结束后并不关闭流
|
* 开始从流中读取Excel,读取结束后并不关闭流
|
||||||
*
|
*
|
||||||
* @param in Excel流
|
* @param in Excel流
|
||||||
* @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet
|
* @param idOrRid Excel中的sheet id或者rid编号,规则如下:
|
||||||
|
* <ul>
|
||||||
|
* <li>如果为-1,处理所有编号的sheet</li>
|
||||||
|
* <li>如果为纯数字,在03中表示index,从0开始,07中表示sheet id,从1开始</li>
|
||||||
|
* </ul>
|
||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
default T read(final InputStream in, final int rid) throws POIException{
|
default T read(final InputStream in, final int idOrRid) throws POIException {
|
||||||
return read(in, String.valueOf(rid));
|
return read(in, String.valueOf(idOrRid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user