This commit is contained in:
Looly
2021-09-25 11:25:51 +08:00
parent 35b9212103
commit e16ec27c40
21 changed files with 183 additions and 251 deletions

View File

@@ -3,7 +3,7 @@
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
# 5.7.14 (2021-09-24) # 5.7.14 (2021-09-25)
### 🐣新特性 ### 🐣新特性
* 【extra 】 修复HttpCookie设置cookies的方法不符合RFC6265规范问题issue#I4B70D@Gitee * 【extra 】 修复HttpCookie设置cookies的方法不符合RFC6265规范问题issue#I4B70D@Gitee
@@ -11,6 +11,7 @@
* 【setting】 增加YamlUtil * 【setting】 增加YamlUtil
* 【extra 】 SenvenZExtractor改名为SevenZExtractor增加getFirst、get方法 * 【extra 】 SenvenZExtractor改名为SevenZExtractor增加getFirst、get方法
* 【core 】 DateConverter修改返回java.util.Date而非DateTimeissue#I4BOAP@Gitee * 【core 】 DateConverter修改返回java.util.Date而非DateTimeissue#I4BOAP@Gitee
* 【core 】 增加IterableIter、ComputeIter
### 🐞Bug修复 ### 🐞Bug修复
* 【http 】 修复HttpCookie设置cookies的方法不符合RFC6265规范问题pr#418@Gitee * 【http 】 修复HttpCookie设置cookies的方法不符合RFC6265规范问题pr#418@Gitee

View File

@@ -2,7 +2,6 @@ package cn.hutool.core.collection;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
/** /**
@@ -12,7 +11,7 @@ import java.util.NoSuchElementException;
* @author Looly * @author Looly
* @since 4.1.1 * @since 4.1.1
*/ */
public class ArrayIter<E> implements Iterator<E>, Iterable<E>, Serializable { public class ArrayIter<E> implements IterableIter<E>, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
@@ -130,10 +129,4 @@ public class ArrayIter<E> implements Iterator<E>, Iterable<E>, Serializable {
public void reset() { public void reset() {
this.index = this.startIndex; this.index = this.startIndex;
} }
@Override
public Iterator<E> iterator() {
return this;
}
} }

View File

@@ -0,0 +1,73 @@
package cn.hutool.core.collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* 带有计算属性的遍历器<br>
* 通过继承此抽象遍历器,实现{@link #computeNext()}计算下一个节点,即可完成节点遍历<br>
* 当调用{@link #hasNext()}时将此方法产生的节点缓存,直到调用{@link #next()}取出<br>
* 当无下一个节点时,须返回{@code null}表示遍历结束
*
* @param <T> 节点类型
* @author looly
* @since 5.7.14
*/
public abstract class ComputeIter<T> implements Iterator<T> {
private T next;
/**
* A flag indicating if the iterator has been fully read.
*/
private boolean finished;
/**
* 计算新的节点,通过实现此方法,当调用{@link #hasNext()}时将此方法产生的节点缓存,直到调用{@link #next()}取出<br>
* 当无下一个节点时,须返回{@code null}表示遍历结束
*
* @return 节点值
*/
protected abstract T computeNext();
@Override
public boolean hasNext() {
if (null != next) {
// 用户读取了节点,但是没有使用
return true;
} else if (finished) {
// 读取结束
return false;
}
T result = computeNext();
if (null == result) {
// 不再有新的节点,结束
this.finished = true;
return false;
} else {
this.next = result;
return true;
}
}
@Override
public T next() {
if (false == hasNext()) {
throw new NoSuchElementException("No more lines");
}
T result = this.next;
// 清空cache表示此节点读取完毕下次计算新节点
this.next = null;
return result;
}
/**
* 手动结束遍历器,用于关闭操作等
*/
public void finish(){
this.finished = true;
this.next = null;
}
}

View File

@@ -95,6 +95,7 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements java.io.Seri
@Override @Override
public boolean contains(Object o) { public boolean contains(Object o) {
//noinspection SuspiciousMethodCalls
return map.containsKey(o); return map.containsKey(o);
} }
@@ -112,4 +113,4 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements java.io.Seri
public void clear() { public void clear() {
map.clear(); map.clear();
} }
} }

View File

@@ -21,7 +21,7 @@ import java.util.List;
* @author Looly * @author Looly
* @since 3.0.7 * @since 3.0.7
*/ */
public class CopiedIter<E> implements Iterator<E>, Iterable<E>, Serializable { public class CopiedIter<E> implements IterableIter<E>, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final Iterator<E> listIterator; private final Iterator<E> listIterator;
@@ -57,10 +57,4 @@ public class CopiedIter<E> implements Iterator<E>, Iterable<E>, Serializable {
public void remove() throws UnsupportedOperationException{ public void remove() throws UnsupportedOperationException{
throw new UnsupportedOperationException("This is a read-only iterator."); throw new UnsupportedOperationException("This is a read-only iterator.");
} }
@Override
public Iterator<E> iterator() {
return this;
}
} }

View File

@@ -11,7 +11,7 @@ import java.util.Iterator;
* @param <E> 元素类型 * @param <E> 元素类型
* @since 4.1.1 * @since 4.1.1
*/ */
public class EnumerationIter<E> implements Iterator<E>, Iterable<E>, Serializable{ public class EnumerationIter<E> implements IterableIter<E>, Serializable{
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final Enumeration<E> e; private final Enumeration<E> e;
@@ -38,10 +38,4 @@ public class EnumerationIter<E> implements Iterator<E>, Iterable<E>, Serializabl
public void remove() { public void remove() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public Iterator<E> iterator() {
return this;
}
} }

View File

@@ -0,0 +1,17 @@
package cn.hutool.core.collection;
import java.util.Iterator;
/**
* 提供合成接口,共同提供{@link Iterable}和{@link Iterator}功能
*
* @param <T> 节点类型
* @author looly
* @since 5.7.14
*/
public interface IterableIter<T> extends Iterable<T>, Iterator<T> {
@Override
default Iterator<T> iterator() {
return this;
}
}

View File

@@ -11,8 +11,6 @@ import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.io.Serializable; import java.io.Serializable;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.NoSuchElementException;
/** /**
* 将Reader包装为一个按照行读取的Iterator<br> * 将Reader包装为一个按照行读取的Iterator<br>
@@ -36,15 +34,10 @@ import java.util.NoSuchElementException;
* @author looly * @author looly
* @since 4.1.1 * @since 4.1.1
*/ */
public class LineIter implements Iterator<String>, Iterable<String>, Closeable, Serializable { public class LineIter extends ComputeIter<String> implements IterableIter<String>, Closeable, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** The reader that is being read. */
private final BufferedReader bufferedReader; private final BufferedReader bufferedReader;
/** The current line. */
private String cachedLine;
/** A flag indicating if the iterator has been fully read. */
private boolean finished = false;
/** /**
* 构造 * 构造
@@ -69,82 +62,31 @@ public class LineIter implements Iterator<String>, Iterable<String>, Closeable,
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
/**
* 判断{@link Reader}是否可以存在下一行。
* If there is an {@code IOException} then {@link #close()} will be called on this instance.
*
* @return {@code true} 表示有更多行
* @throws IORuntimeException IO异常
*/
@Override @Override
public boolean hasNext() throws IORuntimeException { protected String computeNext() {
if (cachedLine != null) { try {
return true; while (true) {
} else if (finished) { String line = bufferedReader.readLine();
return false; if (line == null) {
} else { return null;
try { } else if (isValidLine(line)) {
while (true) { return line;
String line = bufferedReader.readLine();
if (line == null) {
finished = true;
return false;
} else if (isValidLine(line)) {
cachedLine = line;
return true;
}
} }
} catch (IOException ioe) { // 无效行,则跳过进入下一行
close();
throw new IORuntimeException(ioe);
} }
} catch (IOException ioe) {
close();
throw new IORuntimeException(ioe);
} }
} }
/**
* 返回下一行内容
*
* @return 下一行内容
* @throws NoSuchElementException 没有新行
*/
@Override
public String next() throws NoSuchElementException {
return nextLine();
}
/**
* 返回下一行
*
* @return 下一行
* @throws NoSuchElementException 没有更多行
*/
public String nextLine() throws NoSuchElementException {
if (false == hasNext()) {
throw new NoSuchElementException("No more lines");
}
String currentLine = this.cachedLine;
this.cachedLine = null;
return currentLine;
}
/** /**
* 关闭Reader * 关闭Reader
*/ */
@Override @Override
public void close() { public void close() {
finished = true; super.finish();
IoUtil.close(bufferedReader); IoUtil.close(bufferedReader);
cachedLine = null;
}
/**
* 不支持移除
*
* @throws UnsupportedOperationException 始终抛出此异常
*/
@Override
public void remove() {
throw new UnsupportedOperationException("Remove unsupported on LineIterator");
} }
/** /**
@@ -156,9 +98,4 @@ public class LineIter implements Iterator<String>, Iterable<String>, Closeable,
protected boolean isValidLine(String line) { protected boolean isValidLine(String line) {
return true; return true;
} }
@Override
public Iterator<String> iterator() {
return this;
}
} }

View File

@@ -17,7 +17,7 @@ import java.util.List;
* @author qiqi.chen * @author qiqi.chen
* @since 5.7.10 * @since 5.7.10
*/ */
public class PartitionIter<T> implements Iterator<List<T>>, Iterable<List<T>>, Serializable { public class PartitionIter<T> implements IterableIter<List<T>>, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
@@ -40,11 +40,6 @@ public class PartitionIter<T> implements Iterator<List<T>>, Iterable<List<T>>, S
this.partitionSize = partitionSize; this.partitionSize = partitionSize;
} }
@Override
public Iterator<List<T>> iterator() {
return this;
}
@Override @Override
public boolean hasNext() { public boolean hasNext() {
return this.iterator.hasNext(); return this.iterator.hasNext();

View File

@@ -0,0 +1,12 @@
package cn.hutool.core.text.split;
import java.io.Serializable;
public class Splitter implements Serializable {
private static final long serialVersionUID = 1L;
private int limit;
private boolean ignoreEmpty;
private boolean caseInsensitive;
}

View File

@@ -12,7 +12,7 @@ public class PartitionIterTest {
@Test @Test
public void iterTest() { public void iterTest() {
final LineIter lineIter = new LineIter(ResourceUtil.getUtf8Reader("test_lines.csv")); final LineIter lineIter = new LineIter(ResourceUtil.getUtf8Reader("test_lines.csv"));
final PartitionIter<String> iter = new PartitionIter<>(lineIter.iterator(), 3); final PartitionIter<String> iter = new PartitionIter<>(lineIter, 3);
for (List<String> lines : iter) { for (List<String> lines : iter) {
Assert.assertTrue(lines.size() > 0); Assert.assertTrue(lines.size() > 0);
} }

View File

@@ -1,56 +1,26 @@
package cn.hutool.extra.tokenizer; package cn.hutool.extra.tokenizer;
import cn.hutool.core.collection.ComputeIter;
import java.util.Iterator; import java.util.Iterator;
import java.util.NoSuchElementException;
/** /**
* 对于未实现{@link Iterator}接口的普通结果类,装饰为{@link Result}<br> * 对于未实现{@link Iterator}接口的普通结果类,装饰为{@link Result}<br>
* 普通的结果类只需实现{@link #nextWord()} 即可 * 普通的结果类只需实现{@link #nextWord()} 即可
* *
* @author looly * @author looly
* *
*/ */
public abstract class AbstractResult implements Result{ public abstract class AbstractResult extends ComputeIter<Word> implements Result{
private Word cachedWord;
@Override
public boolean hasNext() {
if (this.cachedWord != null) {
return true;
}
final Word next = nextWord();
if(null != next) {
this.cachedWord = next;
return true;
}
return false;
}
/** /**
* 下一个单词通过实现此方法获取下一个单词null表示无下一个结果。 * 下一个单词通过实现此方法获取下一个单词null表示无下一个结果。
* @return 下一个单词或null * @return 下一个单词或null
*/ */
protected abstract Word nextWord(); protected abstract Word nextWord();
@Override
public Word next() {
if (false == hasNext()) {
throw new NoSuchElementException("No more word !");
}
final Word currentWord = this.cachedWord;
this.cachedWord = null;
return currentWord;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Jcseg result not allow to remove !");
}
@Override @Override
public Iterator<Word> iterator() { protected Word computeNext() {
return this; return nextWord();
} }
} }

View File

@@ -1,14 +1,14 @@
package cn.hutool.extra.tokenizer; package cn.hutool.extra.tokenizer;
import java.util.Iterator; import cn.hutool.core.collection.IterableIter;
/** /**
* 分词结果接口定义<br> * 分词结果接口定义<br>
* 实现此接口包装分词器的分词结果通过实现Iterator相应方法获取分词中的单词 * 实现此接口包装分词器的分词结果通过实现Iterator相应方法获取分词中的单词
* *
* @author looly * @author looly
* *
*/ */
public interface Result extends Iterator<Word>, Iterable<Word>{ public interface Result extends IterableIter<Word> {
} }

View File

@@ -1,25 +1,24 @@
package cn.hutool.extra.tokenizer.engine.ansj; package cn.hutool.extra.tokenizer.engine.ansj;
import java.util.Iterator;
import org.ansj.domain.Term;
import cn.hutool.extra.tokenizer.Result; import cn.hutool.extra.tokenizer.Result;
import cn.hutool.extra.tokenizer.Word; import cn.hutool.extra.tokenizer.Word;
import org.ansj.domain.Term;
import java.util.Iterator;
/** /**
* Ansj分词结果实现<br> * Ansj分词结果实现<br>
* 项目地址https://github.com/NLPchina/ansj_seg * 项目地址https://github.com/NLPchina/ansj_seg
*
* @author looly
* *
* @author looly
*/ */
public class AnsjResult implements Result{ public class AnsjResult implements Result {
private final Iterator<Term> result; private final Iterator<Term> result;
/** /**
* 构造 * 构造
*
* @param ansjResult 分词结果 * @param ansjResult 分词结果
*/ */
public AnsjResult(org.ansj.domain.Result ansjResult) { public AnsjResult(org.ansj.domain.Result ansjResult) {

View File

@@ -1,24 +1,23 @@
package cn.hutool.extra.tokenizer.engine.hanlp; package cn.hutool.extra.tokenizer.engine.hanlp;
import cn.hutool.extra.tokenizer.Result;
import cn.hutool.extra.tokenizer.Word;
import com.hankcs.hanlp.seg.common.Term;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import com.hankcs.hanlp.seg.common.Term;
import cn.hutool.extra.tokenizer.Result;
import cn.hutool.extra.tokenizer.Word;
/** /**
* HanLP分词结果实现<br> * HanLP分词结果实现<br>
* 项目地址https://github.com/hankcs/HanLP * 项目地址https://github.com/hankcs/HanLP
* *
* @author looly * @author looly
* *
*/ */
public class HanLPResult implements Result { public class HanLPResult implements Result {
Iterator<Term> result; Iterator<Term> result;
public HanLPResult(List<Term> termList) { public HanLPResult(List<Term> termList) {
this.result = termList.iterator(); this.result = termList.iterator();
} }
@@ -37,11 +36,4 @@ public class HanLPResult implements Result {
public void remove() { public void remove() {
result.remove(); result.remove();
} }
@Override
public Iterator<Word> iterator() {
return this;
}
} }

View File

@@ -11,7 +11,7 @@ import java.io.IOException;
/** /**
* IKAnalyzer分词结果实现<br> * IKAnalyzer分词结果实现<br>
* 项目地址https://github.com/yozhao/IKAnalyzer * 项目地址https://github.com/yozhao/IKAnalyzer
* *
* @author looly * @author looly
* *
*/ */
@@ -21,7 +21,7 @@ public class IKAnalyzerResult extends AbstractResult {
/** /**
* 构造 * 构造
* *
* @param seg 分词结果 * @param seg 分词结果
*/ */
public IKAnalyzerResult(IKSegmenter seg) { public IKAnalyzerResult(IKSegmenter seg) {
@@ -36,9 +36,9 @@ public class IKAnalyzerResult extends AbstractResult {
} catch (IOException e) { } catch (IOException e) {
throw new TokenizerException(e); throw new TokenizerException(e);
} }
if (null != next) { if (null == next) {
return new IKAnalyzerWord(next); return null;
} }
return null; return new IKAnalyzerWord(next);
} }
} }

View File

@@ -1,27 +1,24 @@
package cn.hutool.extra.tokenizer.engine.jcseg; package cn.hutool.extra.tokenizer.engine.jcseg;
import cn.hutool.extra.tokenizer.Result; import cn.hutool.extra.tokenizer.AbstractResult;
import cn.hutool.extra.tokenizer.TokenizerException; import cn.hutool.extra.tokenizer.TokenizerException;
import cn.hutool.extra.tokenizer.Word; import cn.hutool.extra.tokenizer.Word;
import org.lionsoul.jcseg.ISegment; import org.lionsoul.jcseg.ISegment;
import org.lionsoul.jcseg.IWord; import org.lionsoul.jcseg.IWord;
import java.io.IOException; import java.io.IOException;
import java.util.Iterator;
import java.util.NoSuchElementException;
/** /**
* Jcseg分词结果包装<br> * Jcseg分词结果包装<br>
* 项目地址https://gitee.com/lionsoul/jcseg * 项目地址https://gitee.com/lionsoul/jcseg
* *
* @author looly * @author looly
* *
*/ */
public class JcsegResult implements Result{ public class JcsegResult extends AbstractResult {
private final ISegment result; private final ISegment result;
private Word cachedWord;
/** /**
* 构造 * 构造
* @param segment 分词结果 * @param segment 分词结果
@@ -31,41 +28,16 @@ public class JcsegResult implements Result{
} }
@Override @Override
public boolean hasNext() { protected Word nextWord() {
if (this.cachedWord != null) { IWord word;
return true;
}
IWord next;
try { try {
next = this.result.next(); word = this.result.next();
} catch (IOException e) { } catch (IOException e) {
throw new TokenizerException(e); throw new TokenizerException(e);
} }
if(null != next) { if(null == word){
this.cachedWord = new JcsegWord(next); return null;
return true;
} }
return false; return new JcsegWord(word);
} }
@Override
public Word next() {
if (false == hasNext()) {
throw new NoSuchElementException("No more word !");
}
final Word currentWord = this.cachedWord;
this.cachedWord = null;
return currentWord;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Jcseg result not allow to remove !");
}
@Override
public Iterator<Word> iterator() {
return this;
}
} }

View File

@@ -1,24 +1,23 @@
package cn.hutool.extra.tokenizer.engine.jieba; package cn.hutool.extra.tokenizer.engine.jieba;
import cn.hutool.extra.tokenizer.Result;
import cn.hutool.extra.tokenizer.Word;
import com.huaban.analysis.jieba.SegToken;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import com.huaban.analysis.jieba.SegToken;
import cn.hutool.extra.tokenizer.Result;
import cn.hutool.extra.tokenizer.Word;
/** /**
* Jieba分词结果实现<br> * Jieba分词结果实现<br>
* 项目地址https://github.com/huaban/jieba-analysis * 项目地址https://github.com/huaban/jieba-analysis
* *
* @author looly * @author looly
* *
*/ */
public class JiebaResult implements Result{ public class JiebaResult implements Result{
Iterator<SegToken> result; Iterator<SegToken> result;
/** /**
* 构造 * 构造
* @param segTokenList 分词结果 * @param segTokenList 分词结果
@@ -41,10 +40,4 @@ public class JiebaResult implements Result{
public void remove() { public void remove() {
result.remove(); result.remove();
} }
@Override
public Iterator<Word> iterator() {
return this;
}
} }

View File

@@ -10,7 +10,7 @@ import java.io.IOException;
/** /**
* mmseg4j分词结果实现<br> * mmseg4j分词结果实现<br>
* 项目地址https://github.com/chenlb/mmseg4j-core * 项目地址https://github.com/chenlb/mmseg4j-core
* *
* @author looly * @author looly
* *
*/ */
@@ -20,7 +20,7 @@ public class MmsegResult extends AbstractResult {
/** /**
* 构造 * 构造
* *
* @param mmSeg 分词结果 * @param mmSeg 分词结果
*/ */
public MmsegResult(MMSeg mmSeg) { public MmsegResult(MMSeg mmSeg) {
@@ -35,9 +35,9 @@ public class MmsegResult extends AbstractResult {
} catch (IOException e) { } catch (IOException e) {
throw new TokenizerException(e); throw new TokenizerException(e);
} }
if (null != next) { if (null == next) {
return new MmsegWord(next); return null;
} }
return null; return new MmsegWord(next);
} }
} }

View File

@@ -10,17 +10,17 @@ import java.util.Iterator;
/** /**
* MYNLP 中文NLP工具包分词结果实现<br> * MYNLP 中文NLP工具包分词结果实现<br>
* 项目地址https://github.com/mayabot/mynlp/ * 项目地址https://github.com/mayabot/mynlp/
* *
* @author looly * @author looly
* *
*/ */
public class MynlpResult implements Result { public class MynlpResult implements Result {
private final Iterator<WordTerm> result; private final Iterator<WordTerm> result;
/** /**
* 构造 * 构造
* *
* @param sentence 分词结果(中文句子) * @param sentence 分词结果(中文句子)
*/ */
public MynlpResult(Sentence sentence) { public MynlpResult(Sentence sentence) {
@@ -41,9 +41,4 @@ public class MynlpResult implements Result {
public void remove() { public void remove() {
result.remove(); result.remove();
} }
@Override
public Iterator<Word> iterator() {
return this;
}
} }

View File

@@ -9,7 +9,7 @@ import java.util.List;
/** /**
* Word分词结果实现<br> * Word分词结果实现<br>
* 项目地址https://github.com/ysc/word * 项目地址https://github.com/ysc/word
* *
* @author looly * @author looly
* *
*/ */
@@ -19,7 +19,7 @@ public class WordResult implements Result{
/** /**
* 构造 * 构造
* *
* @param result 分词结果 * @param result 分词结果
*/ */
public WordResult(List<org.apdplat.word.segmentation.Word> result) { public WordResult(List<org.apdplat.word.segmentation.Word> result) {
@@ -40,10 +40,4 @@ public class WordResult implements Result{
public void remove() { public void remove() {
this.wordIter.remove(); this.wordIter.remove();
} }
@Override
public Iterator<Word> iterator() {
return this;
}
} }