Compare commits

...

10 Commits

Author SHA1 Message Date
Looly
fceeafebce fix code 2025-11-19 23:08:35 +08:00
Looly
12c86e5bab Merge branch 'v7-dev' of github.com:chinabugotech/hutool into v7-dev 2025-11-19 22:31:42 +08:00
Golden Looly
f95c3ff165
Merge pull request #4134 from Lettuceleaves/perf/optimize-str-finder
Perf/optimize str finder
2025-11-19 22:26:30 +08:00
Looly
342050aab6
!1386 添加ollama模型名称
Merge pull request !1386 from BUG小卖部/v7-dev
2025-11-19 14:10:25 +00:00
zhuhongyu
3e83b6004f 添加ollama模型名称 2025-11-19 10:46:13 +08:00
LettuceLeaves
7578350baa Merge remote-tracking branch 'upstream/v7-dev' into perf/optimize-str-finder 2025-11-19 01:08:30 +08:00
LettuceLeaves
dbed4a4d0f test(core):添加Sunday算法测试 2025-11-19 01:05:44 +08:00
LettuceLeaves
3f15fdd44c perf:使用Sunday算法,优化字串查询 2025-11-19 01:03:42 +08:00
LettuceLeaves
1bba40a32f perf:优化isSubEquals方法,去除toString()防止拷贝 2025-11-19 00:20:56 +08:00
LettuceLeaves
7e8fd78377 test(core):添加 StrFinder 测试用例 2025-11-19 00:03:50 +08:00
136 changed files with 810 additions and 918 deletions

View File

@ -193,7 +193,18 @@ public class Models {
// Ollama的模型 // Ollama的模型
public enum Ollama { public enum Ollama {
QWEN3_32B("qwen3:32b"); QWEN3_32B("qwen3:32b"),
QWEN3_VL_2B("qwen3-vl:2b"),
QWEN3_VL_4B("qwen3-vl:4b"),
QWEN3_VL_8B("qwen3-vl:8b"),
QWEN3_VL_30B("qwen3-vl:30b"),
QWEN3_VL_32B("qwen3-vl:32b"),
DEEPSEEK_R1_7B("deepseek-r1:7b"),
DEEPSEEK_R1_8B("deepseek-r1:8b"),
DEEPSEEK_R1_14B("deepseek-r1:14b"),
DEEPSEEK_R1_32B("deepseek-r1:32b"),
EMBEDDINGGEMMA("embeddinggemma"),
GPT_OSS_20B("gpt-oss:20b");
private final String model; private final String model;

View File

@ -35,7 +35,7 @@ public interface AIService {
* @return AI回答 * @return AI回答
* @since 6.0.0 * @since 6.0.0
*/ */
default String chat(String prompt){ default String chat(final String prompt){
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("system", "You are a helpful assistant")); messages.add(new Message("system", "You are a helpful assistant"));
messages.add(new Message("user", prompt)); messages.add(new Message("user", prompt));
@ -48,7 +48,7 @@ public interface AIService {
* @param callback 流式数据回调函数 * @param callback 流式数据回调函数
* @since 6.0.0 * @since 6.0.0
*/ */
default void chat(String prompt, final Consumer<String> callback){ default void chat(final String prompt, final Consumer<String> callback){
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("system", "You are a helpful assistant")); messages.add(new Message("system", "You are a helpful assistant"));
messages.add(new Message("user", prompt)); messages.add(new Message("user", prompt));

View File

@ -63,8 +63,8 @@ public class DeepSeekServiceImpl extends BaseAIService implements DeepSeekServic
} }
@Override @Override
public void chat(List<Message> messages, Consumer<String> callback) { public void chat(final List<Message> messages, final Consumer<String> callback) {
Map<String, Object> paramMap = buildChatStreamRequestBody(messages); final Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "deepseek-chat-sse").start(); ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "deepseek-chat-sse").start();
} }
@ -76,8 +76,8 @@ public class DeepSeekServiceImpl extends BaseAIService implements DeepSeekServic
} }
@Override @Override
public void beta(String prompt, Consumer<String> callback) { public void beta(final String prompt, final Consumer<String> callback) {
Map<String, Object> paramMap = buildBetaStreamRequestBody(prompt); final Map<String, Object> paramMap = buildBetaStreamRequestBody(prompt);
ThreadUtil.newThread(() -> sendPostStream(BETA_ENDPOINT, paramMap, callback), "deepseek-beta-sse").start(); ThreadUtil.newThread(() -> sendPostStream(BETA_ENDPOINT, paramMap, callback), "deepseek-beta-sse").start();
} }

View File

@ -39,7 +39,7 @@ public interface DoubaoService extends AIService {
* @return AI回答 * @return AI回答
* @since 6.0.0 * @since 6.0.0
*/ */
default String chatVision(String prompt, final List<String> images) { default String chatVision(final String prompt, final List<String> images) {
return chatVision(prompt, images, DoubaoCommon.DoubaoVision.AUTO.getDetail()); return chatVision(prompt, images, DoubaoCommon.DoubaoVision.AUTO.getDetail());
} }
@ -51,7 +51,7 @@ public interface DoubaoService extends AIService {
* @param callback 流式数据回调函数 * @param callback 流式数据回调函数
* @since 6.0.0 * @since 6.0.0
*/ */
default void chatVision(String prompt, final List<String> images, final Consumer<String> callback) { default void chatVision(final String prompt, final List<String> images, final Consumer<String> callback) {
chatVision(prompt, images, DoubaoCommon.DoubaoVision.AUTO.getDetail(), callback); chatVision(prompt, images, DoubaoCommon.DoubaoVision.AUTO.getDetail(), callback);
} }
@ -98,7 +98,7 @@ public interface DoubaoService extends AIService {
* @return 生成任务id * @return 生成任务id
* @since 6.0.0 * @since 6.0.0
*/ */
default String videoTasks(String text, String image) { default String videoTasks(final String text, final String image) {
return videoTasks(text, image, null); return videoTasks(text, image, null);
} }
@ -166,7 +166,7 @@ public interface DoubaoService extends AIService {
* @return AI回答 * @return AI回答
* @since 6.0.0 * @since 6.0.0
*/ */
default String batchChat(String prompt){ default String batchChat(final String prompt){
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("system", "You are a helpful assistant")); messages.add(new Message("system", "You are a helpful assistant"));
messages.add(new Message("user", prompt)); messages.add(new Message("user", prompt));
@ -218,7 +218,7 @@ public interface DoubaoService extends AIService {
* @return AI的回答 * @return AI的回答
* @since 6.0.0 * @since 6.0.0
*/ */
default String chatContext(String prompt, String contextId){ default String chatContext(final String prompt, final String contextId){
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("user", prompt)); messages.add(new Message("user", prompt));
return chatContext(messages, contextId); return chatContext(messages, contextId);
@ -233,7 +233,7 @@ public interface DoubaoService extends AIService {
* @param callback 流式数据回调函数 * @param callback 流式数据回调函数
* @since 6.0.0 * @since 6.0.0
*/ */
default void chatContext(String prompt, String contextId, final Consumer<String> callback){ default void chatContext(final String prompt, final String contextId, final Consumer<String> callback){
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("user", prompt)); messages.add(new Message("user", prompt));
chatContext(messages, contextId, callback); chatContext(messages, contextId, callback);

View File

@ -44,7 +44,7 @@ public class GrokCommon {
private final String detail; private final String detail;
GrokVision(String detail) { GrokVision(final String detail) {
this.detail = detail; this.detail = detail;
} }

View File

@ -49,7 +49,7 @@ public class GrokConfig extends BaseAIConfig {
* *
* @param apiKey API密钥 * @param apiKey API密钥
*/ */
public GrokConfig(String apiKey) { public GrokConfig(final String apiKey) {
this(); this();
setApiKey(apiKey); setApiKey(apiKey);
} }

View File

@ -39,7 +39,7 @@ public interface GrokService extends AIService {
* @return AI回答 * @return AI回答
* @since 6.0.0 * @since 6.0.0
*/ */
default String message(String prompt, int maxToken){ default String message(final String prompt, final int maxToken){
// 定义消息结构 // 定义消息结构
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("system", "You are a helpful assistant")); messages.add(new Message("system", "You are a helpful assistant"));
@ -55,7 +55,7 @@ public interface GrokService extends AIService {
* @param callback 流式数据回调函数 * @param callback 流式数据回调函数
* @since 6.0.0 * @since 6.0.0
*/ */
default void message(String prompt, int maxToken, final Consumer<String> callback){ default void message(final String prompt, final int maxToken, final Consumer<String> callback){
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("system", "You are a helpful assistant")); messages.add(new Message("system", "You are a helpful assistant"));
messages.add(new Message("user", prompt)); messages.add(new Message("user", prompt));
@ -112,7 +112,7 @@ public interface GrokService extends AIService {
* @return AI回答 * @return AI回答
* @since 6.0.0 * @since 6.0.0
*/ */
default String chatVision(String prompt, final List<String> images) { default String chatVision(final String prompt, final List<String> images) {
return chatVision(prompt, images, GrokCommon.GrokVision.AUTO.getDetail()); return chatVision(prompt, images, GrokCommon.GrokVision.AUTO.getDetail());
} }
@ -124,7 +124,7 @@ public interface GrokService extends AIService {
* @param callback 流式数据回调函数 * @param callback 流式数据回调函数
* @since 6.0.0 * @since 6.0.0
*/ */
default void chatVision(String prompt, final List<String> images, final Consumer<String> callback){ default void chatVision(final String prompt, final List<String> images, final Consumer<String> callback){
chatVision(prompt, images, GrokCommon.GrokVision.AUTO.getDetail(), callback); chatVision(prompt, images, GrokCommon.GrokVision.AUTO.getDetail(), callback);
} }

View File

@ -64,84 +64,84 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
@Override @Override
public String chat(final List<Message> messages) { public String chat(final List<Message> messages) {
String paramJson = buildChatRequestBody(messages); final String paramJson = buildChatRequestBody(messages);
Response response = sendPost(CHAT_ENDPOINT, paramJson); final Response response = sendPost(CHAT_ENDPOINT, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public void chat(List<Message> messages, Consumer<String> callback) { public void chat(final List<Message> messages, final Consumer<String> callback) {
Map<String, Object> paramMap = buildChatStreamRequestBody(messages); final Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "grok-chat-sse").start(); ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "grok-chat-sse").start();
} }
@Override @Override
public String message(final List<Message> messages, int maxToken) { public String message(final List<Message> messages, final int maxToken) {
String paramJson = buildMessageRequestBody(messages, maxToken); final String paramJson = buildMessageRequestBody(messages, maxToken);
Response response = sendPost(MESSAGES, paramJson); final Response response = sendPost(MESSAGES, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public void message(List<Message> messages, int maxToken, final Consumer<String> callback) { public void message(final List<Message> messages, final int maxToken, final Consumer<String> callback) {
Map<String, Object> paramMap = buildMessageStreamRequestBody(messages, maxToken); final Map<String, Object> paramMap = buildMessageStreamRequestBody(messages, maxToken);
ThreadUtil.newThread(() -> sendPostStream(MESSAGES, paramMap, callback), "grok-message-sse").start(); ThreadUtil.newThread(() -> sendPostStream(MESSAGES, paramMap, callback), "grok-message-sse").start();
} }
@Override @Override
public String chatVision(String prompt, final List<String> images, String detail) { public String chatVision(final String prompt, final List<String> images, final String detail) {
String paramJson = buildChatVisionRequestBody(prompt, images, detail); final String paramJson = buildChatVisionRequestBody(prompt, images, detail);
Response response = sendPost(CHAT_ENDPOINT, paramJson); final Response response = sendPost(CHAT_ENDPOINT, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public void chatVision(String prompt, List<String> images, String detail, Consumer<String> callback) { public void chatVision(final String prompt, final List<String> images, final String detail, final Consumer<String> callback) {
Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail); final Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail);
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "grok-chatVision-sse").start(); ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "grok-chatVision-sse").start();
} }
@Override @Override
public String models() { public String models() {
Response response = sendGet(MODELS_ENDPOINT); final Response response = sendGet(MODELS_ENDPOINT);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String getModel(String modelId) { public String getModel(final String modelId) {
Response response = sendGet(MODELS_ENDPOINT + "/" + modelId); final Response response = sendGet(MODELS_ENDPOINT + "/" + modelId);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String languageModels() { public String languageModels() {
Response response = sendGet(LANGUAGE_MODELS); final Response response = sendGet(LANGUAGE_MODELS);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String getLanguageModel(String modelId) { public String getLanguageModel(final String modelId) {
Response response = sendGet(LANGUAGE_MODELS + "/" + modelId); final Response response = sendGet(LANGUAGE_MODELS + "/" + modelId);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String tokenizeText(String text) { public String tokenizeText(final String text) {
String paramJson = buildTokenizeRequestBody(text); final String paramJson = buildTokenizeRequestBody(text);
Response response = sendPost(TOKENIZE_TEXT, paramJson); final Response response = sendPost(TOKENIZE_TEXT, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String deferredCompletion(String requestId) { public String deferredCompletion(final String requestId) {
Response response = sendGet(DEFERRED_COMPLETION + "/" + requestId); final Response response = sendGet(DEFERRED_COMPLETION + "/" + requestId);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String imagesGenerations(String prompt) { public String imagesGenerations(final String prompt) {
String paramJson = buildImagesGenerationsRequestBody(prompt); final String paramJson = buildImagesGenerationsRequestBody(prompt);
Response response = sendPost(IMAGES_GENERATIONS, paramJson); final Response response = sendPost(IMAGES_GENERATIONS, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@ -170,7 +170,7 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
} }
//构建chatVision请求体 //构建chatVision请求体
private String buildChatVisionRequestBody(String prompt, final List<String> images, String detail) { private String buildChatVisionRequestBody(final String prompt, final List<String> images, final String detail) {
// 定义消息结构 // 定义消息结构
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
final List<Object> content = new ArrayList<>(); final List<Object> content = new ArrayList<>();
@ -179,10 +179,10 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
contentMap.put("type", "text"); contentMap.put("type", "text");
contentMap.put("text", prompt); contentMap.put("text", prompt);
content.add(contentMap); content.add(contentMap);
for (String img : images) { for (final String img : images) {
HashMap<String, Object> imgUrlMap = new HashMap<>(); final HashMap<String, Object> imgUrlMap = new HashMap<>();
imgUrlMap.put("type", "image_url"); imgUrlMap.put("type", "image_url");
HashMap<String, String> urlMap = new HashMap<>(); final HashMap<String, String> urlMap = new HashMap<>();
urlMap.put("url", img); urlMap.put("url", img);
urlMap.put("detail", detail); urlMap.put("detail", detail);
imgUrlMap.put("image_url", urlMap); imgUrlMap.put("image_url", urlMap);
@ -200,7 +200,7 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
return JSONUtil.toJsonStr(paramMap); return JSONUtil.toJsonStr(paramMap);
} }
private Map<String, Object> buildChatVisionStreamRequestBody(String prompt, final List<String> images, String detail) { private Map<String, Object> buildChatVisionStreamRequestBody(final String prompt, final List<String> images, final String detail) {
// 定义消息结构 // 定义消息结构
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
final List<Object> content = new ArrayList<>(); final List<Object> content = new ArrayList<>();
@ -209,10 +209,10 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
contentMap.put("type", "text"); contentMap.put("type", "text");
contentMap.put("text", prompt); contentMap.put("text", prompt);
content.add(contentMap); content.add(contentMap);
for (String img : images) { for (final String img : images) {
HashMap<String, Object> imgUrlMap = new HashMap<>(); final HashMap<String, Object> imgUrlMap = new HashMap<>();
imgUrlMap.put("type", "image_url"); imgUrlMap.put("type", "image_url");
HashMap<String, String> urlMap = new HashMap<>(); final HashMap<String, String> urlMap = new HashMap<>();
urlMap.put("url", img); urlMap.put("url", img);
urlMap.put("detail", detail); urlMap.put("detail", detail);
imgUrlMap.put("image_url", urlMap); imgUrlMap.put("image_url", urlMap);
@ -232,7 +232,7 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
} }
//构建消息回复请求体 //构建消息回复请求体
private String buildMessageRequestBody(final List<Message> messages, int maxToken) { private String buildMessageRequestBody(final List<Message> messages, final int maxToken) {
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
paramMap.put("messages", messages); paramMap.put("messages", messages);
@ -243,7 +243,7 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
return JSONUtil.toJsonStr(paramMap); return JSONUtil.toJsonStr(paramMap);
} }
private Map<String, Object> buildMessageStreamRequestBody(final List<Message> messages, int maxToken) { private Map<String, Object> buildMessageStreamRequestBody(final List<Message> messages, final int maxToken) {
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("stream", true); paramMap.put("stream", true);
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
@ -256,7 +256,7 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
} }
//构建分词请求体 //构建分词请求体
private String buildTokenizeRequestBody(String text) { private String buildTokenizeRequestBody(final String text) {
//使用JSON工具 //使用JSON工具
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
@ -268,7 +268,7 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
} }
//构建文生图请求体 //构建文生图请求体
private String buildImagesGenerationsRequestBody(String prompt) { private String buildImagesGenerationsRequestBody(final String prompt) {
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
paramMap.put("prompt", prompt); paramMap.put("prompt", prompt);

View File

@ -33,7 +33,7 @@ public class HutoolCommon {
private final String detail; private final String detail;
HutoolVision(String detail) { HutoolVision(final String detail) {
this.detail = detail; this.detail = detail;
} }
@ -57,7 +57,7 @@ public class HutoolCommon {
private final String voice; private final String voice;
HutoolSpeech(String voice) { HutoolSpeech(final String voice) {
this.voice = voice; this.voice = voice;
} }
@ -94,7 +94,7 @@ public class HutoolCommon {
private final String type; private final String type;
private final Object value; private final Object value;
HutoolVideo(String type, Object value) { HutoolVideo(final String type, final Object value) {
this.type = type; this.type = type;
this.value = value; this.value = value;
} }

View File

@ -36,7 +36,7 @@ public class HutoolConfig extends BaseAIConfig {
setModel(DEFAULT_MODEL); setModel(DEFAULT_MODEL);
} }
public HutoolConfig(String apiKey) { public HutoolConfig(final String apiKey) {
this(); this();
setApiKey(apiKey); setApiKey(apiKey);
} }

View File

@ -61,7 +61,7 @@ public interface HutoolService extends AIService {
* @return AI回答 * @return AI回答
* @since 6.0.0 * @since 6.0.0
*/ */
default String chatVision(String prompt, final List<String> images) { default String chatVision(final String prompt, final List<String> images) {
return chatVision(prompt, images, HutoolCommon.HutoolVision.AUTO.getDetail()); return chatVision(prompt, images, HutoolCommon.HutoolVision.AUTO.getDetail());
} }
@ -73,7 +73,7 @@ public interface HutoolService extends AIService {
* @param callback 流式数据回调函数 * @param callback 流式数据回调函数
* @since 6.0.0 * @since 6.0.0
*/ */
default void chatVision(String prompt, final List<String> images, final Consumer<String> callback){ default void chatVision(final String prompt, final List<String> images, final Consumer<String> callback){
chatVision(prompt, images, HutoolCommon.HutoolVision.AUTO.getDetail(), callback); chatVision(prompt, images, HutoolCommon.HutoolVision.AUTO.getDetail(), callback);
} }
@ -122,7 +122,7 @@ public interface HutoolService extends AIService {
* @return 返回的音频mp3文件流 * @return 返回的音频mp3文件流
* @since 6.0.0 * @since 6.0.0
*/ */
default InputStream tts(String input) { default InputStream tts(final String input) {
return tts(input, HutoolCommon.HutoolSpeech.ALLOY); return tts(input, HutoolCommon.HutoolSpeech.ALLOY);
} }
@ -154,7 +154,7 @@ public interface HutoolService extends AIService {
* @return 生成任务id * @return 生成任务id
* @since 6.0.0 * @since 6.0.0
*/ */
default String videoTasks(String text, String image) { default String videoTasks(final String text, final String image) {
return videoTasks(text, image, null); return videoTasks(text, image, null);
} }

View File

@ -63,69 +63,69 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
@Override @Override
public String chat(final List<Message> messages) { public String chat(final List<Message> messages) {
String paramJson = buildChatRequestBody(messages); final String paramJson = buildChatRequestBody(messages);
Response response = sendPost(CHAT_ENDPOINT, paramJson); final Response response = sendPost(CHAT_ENDPOINT, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public void chat(List<Message> messages,Consumer<String> callback) { public void chat(final List<Message> messages, final Consumer<String> callback) {
Map<String, Object> paramMap = buildChatStreamRequestBody(messages); final Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "hutool-chat-sse").start(); ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "hutool-chat-sse").start();
} }
@Override @Override
public String chatVision(String prompt, final List<String> images, String detail) { public String chatVision(final String prompt, final List<String> images, final String detail) {
String paramJson = buildChatVisionRequestBody(prompt, images, detail); final String paramJson = buildChatVisionRequestBody(prompt, images, detail);
Response response = sendPost(CHAT_ENDPOINT, paramJson); final Response response = sendPost(CHAT_ENDPOINT, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public void chatVision(String prompt, List<String> images, String detail, Consumer<String> callback) { public void chatVision(final String prompt, final List<String> images, final String detail, final Consumer<String> callback) {
Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail); final Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail);
System.out.println(JSONUtil.toJsonStr(paramMap)); System.out.println(JSONUtil.toJsonStr(paramMap));
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "hutool-chatVision-sse").start(); ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "hutool-chatVision-sse").start();
} }
@Override @Override
public String tokenizeText(String text) { public String tokenizeText(final String text) {
String paramJson = buildTokenizeRequestBody(text); final String paramJson = buildTokenizeRequestBody(text);
Response response = sendPost(TOKENIZE_TEXT, paramJson); final Response response = sendPost(TOKENIZE_TEXT, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String imagesGenerations(String prompt) { public String imagesGenerations(final String prompt) {
String paramJson = buildImagesGenerationsRequestBody(prompt); final String paramJson = buildImagesGenerationsRequestBody(prompt);
Response response = sendPost(IMAGES_GENERATIONS, paramJson); final Response response = sendPost(IMAGES_GENERATIONS, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String embeddingVision(String text, String image) { public String embeddingVision(final String text, final String image) {
String paramJson = buildEmbeddingVisionRequestBody(text, image); final String paramJson = buildEmbeddingVisionRequestBody(text, image);
Response response = sendPost(EMBEDDING_VISION, paramJson); final Response response = sendPost(EMBEDDING_VISION, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public InputStream tts(String input, final HutoolCommon.HutoolSpeech voice) { public InputStream tts(final String input, final HutoolCommon.HutoolSpeech voice) {
try { try {
String paramJson = buildTTSRequestBody(input, voice.getVoice()); final String paramJson = buildTTSRequestBody(input, voice.getVoice());
Response response = sendPost(TTS, paramJson); final Response response = sendPost(TTS, paramJson);
// 检查响应内容类型 // 检查响应内容类型
String contentType = response.header("Content-Type"); final String contentType = response.header("Content-Type");
if (contentType != null && contentType.startsWith("application/json")) { if (contentType != null && contentType.startsWith("application/json")) {
// 如果是JSON响应说明有错误 // 如果是JSON响应说明有错误
String errorBody = response.bodyStr(); final String errorBody = response.bodyStr();
throw new AIException("TTS请求失败: " + errorBody); throw new AIException("TTS请求失败: " + errorBody);
} }
// 默认返回音频流 // 默认返回音频流
return response.bodyStream(); return response.bodyStream();
} catch (Exception e) { } catch (final Exception e) {
throw new AIException("TTS处理失败: " + e.getMessage(), e); throw new AIException("TTS处理失败: " + e.getMessage(), e);
} }
} }
@ -133,21 +133,21 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
@Override @Override
public String stt(final File file) { public String stt(final File file) {
final Map<String, Object> paramMap = buildSTTRequestBody(file); final Map<String, Object> paramMap = buildSTTRequestBody(file);
Response response = sendFormData(STT, paramMap); final Response response = sendFormData(STT, paramMap);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String videoTasks(String text, String image, final List<HutoolCommon.HutoolVideo> videoParams) { public String videoTasks(final String text, final String image, final List<HutoolCommon.HutoolVideo> videoParams) {
String paramJson = buildGenerationsTasksRequestBody(text, image, videoParams); final String paramJson = buildGenerationsTasksRequestBody(text, image, videoParams);
Response response = sendPost(CREATE_VIDEO, paramJson); final Response response = sendPost(CREATE_VIDEO, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String getVideoTasksInfo(String taskId) { public String getVideoTasksInfo(final String taskId) {
Response response = sendGet(CREATE_VIDEO + "/" + taskId); final Response response = sendGet(CREATE_VIDEO + "/" + taskId);
return response.bodyStr(); return response.bodyStr();
} }
@ -177,7 +177,7 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
} }
//构建chatVision请求体 //构建chatVision请求体
private String buildChatVisionRequestBody(String prompt, final List<String> images, String detail) { private String buildChatVisionRequestBody(final String prompt, final List<String> images, final String detail) {
// 定义消息结构 // 定义消息结构
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
final List<Object> content = new ArrayList<>(); final List<Object> content = new ArrayList<>();
@ -186,10 +186,10 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
contentMap.put("type", "text"); contentMap.put("type", "text");
contentMap.put("text", prompt); contentMap.put("text", prompt);
content.add(contentMap); content.add(contentMap);
for (String img : images) { for (final String img : images) {
HashMap<String, Object> imgUrlMap = new HashMap<>(); final HashMap<String, Object> imgUrlMap = new HashMap<>();
imgUrlMap.put("type", "image_url"); imgUrlMap.put("type", "image_url");
HashMap<String, String> urlMap = new HashMap<>(); final HashMap<String, String> urlMap = new HashMap<>();
urlMap.put("url", img); urlMap.put("url", img);
urlMap.put("detail", detail); urlMap.put("detail", detail);
imgUrlMap.put("image_url", urlMap); imgUrlMap.put("image_url", urlMap);
@ -207,7 +207,7 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
return JSONUtil.toJsonStr(paramMap); return JSONUtil.toJsonStr(paramMap);
} }
private Map<String, Object> buildChatVisionStreamRequestBody(String prompt, final List<String> images, String detail) { private Map<String, Object> buildChatVisionStreamRequestBody(final String prompt, final List<String> images, final String detail) {
// 定义消息结构 // 定义消息结构
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
final List<Object> content = new ArrayList<>(); final List<Object> content = new ArrayList<>();
@ -216,10 +216,10 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
contentMap.put("type", "text"); contentMap.put("type", "text");
contentMap.put("text", prompt); contentMap.put("text", prompt);
content.add(contentMap); content.add(contentMap);
for (String img : images) { for (final String img : images) {
HashMap<String, Object> imgUrlMap = new HashMap<>(); final HashMap<String, Object> imgUrlMap = new HashMap<>();
imgUrlMap.put("type", "image_url"); imgUrlMap.put("type", "image_url");
HashMap<String, String> urlMap = new HashMap<>(); final HashMap<String, String> urlMap = new HashMap<>();
urlMap.put("url", img); urlMap.put("url", img);
urlMap.put("detail", detail); urlMap.put("detail", detail);
imgUrlMap.put("image_url", urlMap); imgUrlMap.put("image_url", urlMap);
@ -240,7 +240,7 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
//构建分词请求体 //构建分词请求体
private String buildTokenizeRequestBody(String text) { private String buildTokenizeRequestBody(final String text) {
//使用JSON工具 //使用JSON工具
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
@ -252,7 +252,7 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
} }
//构建文生图请求体 //构建文生图请求体
private String buildImagesGenerationsRequestBody(String prompt) { private String buildImagesGenerationsRequestBody(final String prompt) {
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
paramMap.put("prompt", prompt); paramMap.put("prompt", prompt);
@ -263,7 +263,7 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
} }
//构建图文向量化请求体 //构建图文向量化请求体
private String buildEmbeddingVisionRequestBody(String text, String image) { private String buildEmbeddingVisionRequestBody(final String text, final String image) {
//使用JSON工具 //使用JSON工具
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
@ -295,7 +295,7 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
//构建TTS请求体 //构建TTS请求体
private String buildTTSRequestBody(String input, String voice) { private String buildTTSRequestBody(final String input, final String voice) {
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
paramMap.put("input", input); paramMap.put("input", input);
@ -318,7 +318,7 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
} }
//构建创建视频任务请求体 //构建创建视频任务请求体
private String buildGenerationsTasksRequestBody(String text, String image, final List<HutoolCommon.HutoolVideo> videoParams) { private String buildGenerationsTasksRequestBody(final String text, final String image, final List<HutoolCommon.HutoolVideo> videoParams) {
//使用JSON工具 //使用JSON工具
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
@ -345,9 +345,9 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
if (videoParams != null && !videoParams.isEmpty()) { if (videoParams != null && !videoParams.isEmpty()) {
//如果有文本参数就加在后面 //如果有文本参数就加在后面
if (textMap != null && !textMap.isEmpty()) { if (textMap != null && !textMap.isEmpty()) {
int textIndex = content.indexOf(textMap); final int textIndex = content.indexOf(textMap);
StringBuilder textBuilder = new StringBuilder(text); final StringBuilder textBuilder = new StringBuilder(text);
for (HutoolCommon.HutoolVideo videoParam : videoParams) { for (final HutoolCommon.HutoolVideo videoParam : videoParams) {
textBuilder.append(" ").append(videoParam.getType()).append(" ").append(videoParam.getValue()); textBuilder.append(" ").append(videoParam.getType()).append(" ").append(videoParam.getValue());
} }
textMap.put("type", "text"); textMap.put("type", "text");
@ -360,8 +360,8 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
} }
} else { } else {
//如果没有文本参数就重新增加 //如果没有文本参数就重新增加
StringBuilder textBuilder = new StringBuilder(); final StringBuilder textBuilder = new StringBuilder();
for (HutoolCommon.HutoolVideo videoParam : videoParams) { for (final HutoolCommon.HutoolVideo videoParam : videoParams) {
textBuilder.append(videoParam.getType()).append(videoParam.getValue()).append(" "); textBuilder.append(videoParam.getType()).append(videoParam.getValue()).append(" ");
} }
textMap.put("type", "text"); textMap.put("type", "text");

View File

@ -39,7 +39,7 @@ public class OllamaCommon {
private final String format; private final String format;
OllamaFormat(String format) { OllamaFormat(final String format) {
this.format = format; this.format = format;
} }

View File

@ -36,12 +36,12 @@ public class OllamaConfig extends BaseAIConfig {
setModel(DEFAULT_MODEL); setModel(DEFAULT_MODEL);
} }
public OllamaConfig(String apiUrl) { public OllamaConfig(final String apiUrl) {
this(); this();
setApiUrl(apiUrl); setApiUrl(apiUrl);
} }
public OllamaConfig(String apiUrl, String model) { public OllamaConfig(final String apiUrl, final String model) {
this(); this();
setApiUrl(apiUrl); setApiUrl(apiUrl);
setModel(model); setModel(model);

View File

@ -130,7 +130,7 @@ public interface OllamaService extends AIService {
* @return AI回答 * @return AI回答
* @since 5.8.40 * @since 5.8.40
*/ */
default String chat(String prompt) { default String chat(final String prompt) {
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("user", prompt)); messages.add(new Message("user", prompt));
return chat(messages); return chat(messages);
@ -143,7 +143,7 @@ public interface OllamaService extends AIService {
* @param callback 流式数据回调函数 * @param callback 流式数据回调函数
* @since 5.8.40 * @since 5.8.40
*/ */
default void chat(String prompt, Consumer<String> callback) { default void chat(final String prompt, final Consumer<String> callback) {
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("user", prompt)); messages.add(new Message("user", prompt));
chat(messages, callback); chat(messages, callback);

View File

@ -33,7 +33,7 @@ public class OpenaiCommon {
private final String effort; private final String effort;
OpenaiReasoning(String effort) { OpenaiReasoning(final String effort) {
this.effort = effort; this.effort = effort;
} }
@ -51,7 +51,7 @@ public class OpenaiCommon {
private final String detail; private final String detail;
OpenaiVision(String detail) { OpenaiVision(final String detail) {
this.detail = detail; this.detail = detail;
} }
@ -75,7 +75,7 @@ public class OpenaiCommon {
private final String voice; private final String voice;
OpenaiSpeech(String voice) { OpenaiSpeech(final String voice) {
this.voice = voice; this.voice = voice;
} }

View File

@ -36,7 +36,7 @@ public class OpenaiConfig extends BaseAIConfig {
setModel(DEFAULT_MODEL); setModel(DEFAULT_MODEL);
} }
public OpenaiConfig(String apiKey) { public OpenaiConfig(final String apiKey) {
this(); this();
setApiKey(apiKey); setApiKey(apiKey);
} }

View File

@ -63,7 +63,7 @@ public interface OpenaiService extends AIService {
* @return AI回答 * @return AI回答
* @since 6.0.0 * @since 6.0.0
*/ */
default String chatVision(String prompt, final List<String> images) { default String chatVision(final String prompt, final List<String> images) {
return chatVision(prompt, images, OpenaiCommon.OpenaiVision.AUTO.getDetail()); return chatVision(prompt, images, OpenaiCommon.OpenaiVision.AUTO.getDetail());
} }
@ -75,7 +75,7 @@ public interface OpenaiService extends AIService {
* @param callback 流式数据回调函数 * @param callback 流式数据回调函数
* @since 6.0.0 * @since 6.0.0
*/ */
default void chatVision(String prompt, final List<String> images, final Consumer<String> callback){ default void chatVision(final String prompt, final List<String> images, final Consumer<String> callback){
chatVision(prompt, images, OpenaiCommon.OpenaiVision.AUTO.getDetail(), callback); chatVision(prompt, images, OpenaiCommon.OpenaiVision.AUTO.getDetail(), callback);
} }
@ -107,7 +107,7 @@ public interface OpenaiService extends AIService {
* @return 包含生成图片的url * @return 包含生成图片的url
* @since 6.0.0 * @since 6.0.0
*/ */
default String imagesEdits(String prompt, final File image) { default String imagesEdits(final String prompt, final File image) {
return imagesEdits(prompt, image, null); return imagesEdits(prompt, image, null);
} }
@ -137,7 +137,7 @@ public interface OpenaiService extends AIService {
* @return 返回的音频mp3文件流 * @return 返回的音频mp3文件流
* @since 6.0.0 * @since 6.0.0
*/ */
default InputStream textToSpeech(String input) { default InputStream textToSpeech(final String input) {
return textToSpeech(input, OpenaiCommon.OpenaiSpeech.ALLOY); return textToSpeech(input, OpenaiCommon.OpenaiSpeech.ALLOY);
} }
@ -178,7 +178,7 @@ public interface OpenaiService extends AIService {
* @return AI返回结果 * @return AI返回结果
* @since 6.0.0 * @since 6.0.0
*/ */
default String moderations(String text) { default String moderations(final String text) {
return moderations(text, null); return moderations(text, null);
} }
@ -191,7 +191,7 @@ public interface OpenaiService extends AIService {
* @return AI回答 * @return AI回答
* @since 6.0.0 * @since 6.0.0
*/ */
default String chatReasoning(String prompt, String reasoningEffort){ default String chatReasoning(final String prompt, final String reasoningEffort){
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("system", "You are a helpful assistant")); messages.add(new Message("system", "You are a helpful assistant"));
messages.add(new Message("user", prompt)); messages.add(new Message("user", prompt));
@ -207,7 +207,7 @@ public interface OpenaiService extends AIService {
* @param callback 流式数据回调函数 * @param callback 流式数据回调函数
* @since 6.0.0 * @since 6.0.0
*/ */
default void chatReasoning(String prompt, String reasoningEffort, final Consumer<String> callback){ default void chatReasoning(final String prompt, final String reasoningEffort, final Consumer<String> callback){
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("system", "You are a helpful assistant")); messages.add(new Message("system", "You are a helpful assistant"));
messages.add(new Message("user", prompt)); messages.add(new Message("user", prompt));
@ -222,7 +222,7 @@ public interface OpenaiService extends AIService {
* @return AI回答 * @return AI回答
* @since 6.0.0 * @since 6.0.0
*/ */
default String chatReasoning(String prompt) { default String chatReasoning(final String prompt) {
return chatReasoning(prompt, OpenaiCommon.OpenaiReasoning.MEDIUM.getEffort()); return chatReasoning(prompt, OpenaiCommon.OpenaiReasoning.MEDIUM.getEffort());
} }
@ -234,7 +234,7 @@ public interface OpenaiService extends AIService {
* @param callback 流式数据回调函数 * @param callback 流式数据回调函数
* @since 6.0.0 * @since 6.0.0
*/ */
default void chatReasoning(String prompt, final Consumer<String> callback) { default void chatReasoning(final String prompt, final Consumer<String> callback) {
chatReasoning(prompt, OpenaiCommon.OpenaiReasoning.MEDIUM.getEffort(), callback); chatReasoning(prompt, OpenaiCommon.OpenaiReasoning.MEDIUM.getEffort(), callback);
} }

View File

@ -64,89 +64,89 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
@Override @Override
public String chat(final List<Message> messages) { public String chat(final List<Message> messages) {
String paramJson = buildChatRequestBody(messages); final String paramJson = buildChatRequestBody(messages);
Response response = sendPost(CHAT_ENDPOINT, paramJson); final Response response = sendPost(CHAT_ENDPOINT, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public void chat(List<Message> messages, Consumer<String> callback) { public void chat(final List<Message> messages, final Consumer<String> callback) {
Map<String, Object> paramMap = buildChatStreamRequestBody(messages); final Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "openai-chat-sse").start(); ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "openai-chat-sse").start();
} }
@Override @Override
public String chatVision(String prompt, final List<String> images, String detail) { public String chatVision(final String prompt, final List<String> images, final String detail) {
String paramJson = buildChatVisionRequestBody(prompt, images, detail); final String paramJson = buildChatVisionRequestBody(prompt, images, detail);
Response response = sendPost(CHAT_ENDPOINT, paramJson); final Response response = sendPost(CHAT_ENDPOINT, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public void chatVision(String prompt, List<String> images, String detail, Consumer<String> callback) { public void chatVision(final String prompt, final List<String> images, final String detail, final Consumer<String> callback) {
Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail); final Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail);
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "openai-chatVision-sse").start(); ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "openai-chatVision-sse").start();
} }
@Override @Override
public String imagesGenerations(String prompt) { public String imagesGenerations(final String prompt) {
String paramJson = buildImagesGenerationsRequestBody(prompt); final String paramJson = buildImagesGenerationsRequestBody(prompt);
Response response = sendPost(IMAGES_GENERATIONS, paramJson); final Response response = sendPost(IMAGES_GENERATIONS, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String imagesEdits(String prompt, final File image, final File mask) { public String imagesEdits(final String prompt, final File image, final File mask) {
final Map<String, Object> paramMap = buildImagesEditsRequestBody(prompt, image, mask); final Map<String, Object> paramMap = buildImagesEditsRequestBody(prompt, image, mask);
Response response = sendFormData(IMAGES_EDITS, paramMap); final Response response = sendFormData(IMAGES_EDITS, paramMap);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String imagesVariations(final File image) { public String imagesVariations(final File image) {
final Map<String, Object> paramMap = buildImagesVariationsRequestBody(image); final Map<String, Object> paramMap = buildImagesVariationsRequestBody(image);
Response response = sendFormData(IMAGES_VARIATIONS, paramMap); final Response response = sendFormData(IMAGES_VARIATIONS, paramMap);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public InputStream textToSpeech(String input, final OpenaiCommon.OpenaiSpeech voice) { public InputStream textToSpeech(final String input, final OpenaiCommon.OpenaiSpeech voice) {
String paramJson = buildTTSRequestBody(input, voice.getVoice()); final String paramJson = buildTTSRequestBody(input, voice.getVoice());
Response response = sendPost(TTS, paramJson); final Response response = sendPost(TTS, paramJson);
return response.bodyStream(); return response.bodyStream();
} }
@Override @Override
public String speechToText(final File file) { public String speechToText(final File file) {
final Map<String, Object> paramMap = buildSTTRequestBody(file); final Map<String, Object> paramMap = buildSTTRequestBody(file);
Response response = sendFormData(STT, paramMap); final Response response = sendFormData(STT, paramMap);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String embeddingText(String input) { public String embeddingText(final String input) {
String paramJson = buildEmbeddingTextRequestBody(input); final String paramJson = buildEmbeddingTextRequestBody(input);
Response response = sendPost(EMBEDDINGS, paramJson); final Response response = sendPost(EMBEDDINGS, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String moderations(String text, String imgUrl) { public String moderations(final String text, final String imgUrl) {
String paramJson = buileModerationsRequestBody(text, imgUrl); final String paramJson = buileModerationsRequestBody(text, imgUrl);
Response response = sendPost(MODERATIONS, paramJson); final Response response = sendPost(MODERATIONS, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public String chatReasoning(final List<Message> messages, String reasoningEffort) { public String chatReasoning(final List<Message> messages, final String reasoningEffort) {
String paramJson = buildChatReasoningRequestBody(messages, reasoningEffort); final String paramJson = buildChatReasoningRequestBody(messages, reasoningEffort);
Response response = sendPost(CHAT_ENDPOINT, paramJson); final Response response = sendPost(CHAT_ENDPOINT, paramJson);
return response.bodyStr(); return response.bodyStr();
} }
@Override @Override
public void chatReasoning(List<Message> messages, String reasoningEffort, Consumer<String> callback) { public void chatReasoning(final List<Message> messages, final String reasoningEffort, final Consumer<String> callback) {
Map<String, Object> paramMap = buildChatReasoningStreamRequestBody(messages, reasoningEffort); final Map<String, Object> paramMap = buildChatReasoningStreamRequestBody(messages, reasoningEffort);
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "openai-chatReasoning-sse").start(); ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "openai-chatReasoning-sse").start();
} }
@ -175,7 +175,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
} }
//构建chatVision请求体 //构建chatVision请求体
private String buildChatVisionRequestBody(String prompt, final List<String> images, String detail) { private String buildChatVisionRequestBody(final String prompt, final List<String> images, final String detail) {
// 定义消息结构 // 定义消息结构
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
final List<Object> content = new ArrayList<>(); final List<Object> content = new ArrayList<>();
@ -184,7 +184,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
contentMap.put("type", "text"); contentMap.put("type", "text");
contentMap.put("text", prompt); contentMap.put("text", prompt);
content.add(contentMap); content.add(contentMap);
for (String img : images) { for (final String img : images) {
final Map<String, Object> imgUrlMap = new HashMap<>(); final Map<String, Object> imgUrlMap = new HashMap<>();
imgUrlMap.put("type", "image_url"); imgUrlMap.put("type", "image_url");
final Map<String, String> urlMap = new HashMap<>(); final Map<String, String> urlMap = new HashMap<>();
@ -205,7 +205,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
return JSONUtil.toJsonStr(paramMap); return JSONUtil.toJsonStr(paramMap);
} }
private Map<String, Object> buildChatVisionStreamRequestBody(String prompt, final List<String> images, String detail) { private Map<String, Object> buildChatVisionStreamRequestBody(final String prompt, final List<String> images, final String detail) {
// 定义消息结构 // 定义消息结构
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
final List<Object> content = new ArrayList<>(); final List<Object> content = new ArrayList<>();
@ -214,10 +214,10 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
contentMap.put("type", "text"); contentMap.put("type", "text");
contentMap.put("text", prompt); contentMap.put("text", prompt);
content.add(contentMap); content.add(contentMap);
for (String img : images) { for (final String img : images) {
HashMap<String, Object> imgUrlMap = new HashMap<>(); final HashMap<String, Object> imgUrlMap = new HashMap<>();
imgUrlMap.put("type", "image_url"); imgUrlMap.put("type", "image_url");
HashMap<String, String> urlMap = new HashMap<>(); final HashMap<String, String> urlMap = new HashMap<>();
urlMap.put("url", img); urlMap.put("url", img);
urlMap.put("detail", detail); urlMap.put("detail", detail);
imgUrlMap.put("image_url", urlMap); imgUrlMap.put("image_url", urlMap);
@ -237,7 +237,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
} }
//构建文生图请求体 //构建文生图请求体
private String buildImagesGenerationsRequestBody(String prompt) { private String buildImagesGenerationsRequestBody(final String prompt) {
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
paramMap.put("prompt", prompt); paramMap.put("prompt", prompt);
@ -248,7 +248,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
} }
//构建图片编辑请求体 //构建图片编辑请求体
private Map<String, Object> buildImagesEditsRequestBody(String prompt, final File image, final File mask) { private Map<String, Object> buildImagesEditsRequestBody(final String prompt, final File image, final File mask) {
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
paramMap.put("prompt", prompt); paramMap.put("prompt", prompt);
@ -274,7 +274,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
} }
//构建TTS请求体 //构建TTS请求体
private String buildTTSRequestBody(String input, String voice) { private String buildTTSRequestBody(final String input, final String voice) {
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
paramMap.put("input", input); paramMap.put("input", input);
@ -297,7 +297,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
} }
//构建文本向量化请求体 //构建文本向量化请求体
private String buildEmbeddingTextRequestBody(String input) { private String buildEmbeddingTextRequestBody(final String input) {
//使用JSON工具 //使用JSON工具
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
@ -308,7 +308,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
} }
//构建检查图片或文字请求体 //构建检查图片或文字请求体
private String buileModerationsRequestBody(String text, String imgUrl) { private String buileModerationsRequestBody(final String text, final String imgUrl) {
//使用JSON工具 //使用JSON工具
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
@ -339,7 +339,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
} }
//构建推理请求体 //构建推理请求体
private String buildChatReasoningRequestBody(final List<Message> messages, String reasoningEffort) { private String buildChatReasoningRequestBody(final List<Message> messages, final String reasoningEffort) {
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());
paramMap.put("messages", messages); paramMap.put("messages", messages);
@ -350,7 +350,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
return JSONUtil.toJsonStr(paramMap); return JSONUtil.toJsonStr(paramMap);
} }
private Map<String, Object> buildChatReasoningStreamRequestBody(final List<Message> messages, String reasoningEffort) { private Map<String, Object> buildChatReasoningStreamRequestBody(final List<Message> messages, final String reasoningEffort) {
final Map<String, Object> paramMap = new HashMap<>(); final Map<String, Object> paramMap = new HashMap<>();
paramMap.put("stream", true); paramMap.put("stream", true);
paramMap.put("model", config.getModel()); paramMap.put("model", config.getModel());

View File

@ -45,9 +45,9 @@ class DeepSeekServiceTest {
@Test @Test
@Disabled @Disabled
void chatStream() { void chatStream() {
String prompt = "写一个疯狂星期四广告词"; final String prompt = "写一个疯狂星期四广告词";
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
deepSeekService.chat(prompt, data -> { deepSeekService.chat(prompt, data -> {
assertNotNull(data); assertNotNull(data);
@ -85,9 +85,9 @@ class DeepSeekServiceTest {
@Test @Test
@Disabled @Disabled
void betaStream() { void betaStream() {
String beta = "写一个疯狂星期四广告词"; final String beta = "写一个疯狂星期四广告词";
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
deepSeekService.beta(beta, data -> { deepSeekService.beta(beta, data -> {
assertNotNull(data); assertNotNull(data);

View File

@ -48,9 +48,9 @@ class DoubaoServiceTest {
@Test @Test
@Disabled @Disabled
void chatStream() { void chatStream() {
String prompt = "写一个疯狂星期四广告词"; final String prompt = "写一个疯狂星期四广告词";
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
doubaoService.chat(prompt, data -> { doubaoService.chat(prompt, data -> {
assertNotNull(data); assertNotNull(data);
@ -94,11 +94,11 @@ class DoubaoServiceTest {
final DoubaoService doubaoService = AIServiceFactory.getAIService(new AIConfigBuilder(ModelName.DOUBAO.getValue()) final DoubaoService doubaoService = AIServiceFactory.getAIService(new AIConfigBuilder(ModelName.DOUBAO.getValue())
.setApiKey(key).setModel(Models.Doubao.DOUBAO_1_5_VISION_PRO_32K.getModel()).build(), DoubaoService.class); .setApiKey(key).setModel(Models.Doubao.DOUBAO_1_5_VISION_PRO_32K.getModel()).build(), DoubaoService.class);
String prompt = "图片上有些什么?"; final String prompt = "图片上有些什么?";
List<String> images = List.of("https://img2.baidu.com/it/u=862000265,4064861820&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1544"); final List<String> images = List.of("https://img2.baidu.com/it/u=862000265,4064861820&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1544");
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
doubaoService.chatVision(prompt,images, data -> { doubaoService.chatVision(prompt,images, data -> {
assertNotNull(data); assertNotNull(data);
if (data.contains("[DONE]")) { if (data.contains("[DONE]")) {
@ -184,7 +184,7 @@ class DoubaoServiceTest {
messages.add(new Message("user","你想做些什么")); messages.add(new Message("user","你想做些什么"));
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
doubaoService.botsChat(messages, data -> { doubaoService.botsChat(messages, data -> {
assertNotNull(data); assertNotNull(data);
if (data.contains("[DONE]")) { if (data.contains("[DONE]")) {
@ -278,10 +278,10 @@ class DoubaoServiceTest {
.setApiKey(key).setModel("your Endpoint ID").build(), DoubaoService.class); .setApiKey(key).setModel("your Endpoint ID").build(), DoubaoService.class);
final List<Message> messages = new ArrayList<>(); final List<Message> messages = new ArrayList<>();
messages.add(new Message("user","你怎么看待意大利面拌水泥?")); messages.add(new Message("user","你怎么看待意大利面拌水泥?"));
String contextId = "your contextId"; final String contextId = "your contextId";
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
doubaoService.chatContext(messages,contextId, data -> { doubaoService.chatContext(messages,contextId, data -> {
assertNotNull(data); assertNotNull(data);
if (data.contains("[DONE]")) { if (data.contains("[DONE]")) {

View File

@ -49,9 +49,9 @@ class GrokServiceTest {
@Test @Test
@Disabled @Disabled
void chatStream() { void chatStream() {
String prompt = "写一个疯狂星期四广告词"; final String prompt = "写一个疯狂星期四广告词";
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
grokService.chat(prompt, data -> { grokService.chat(prompt, data -> {
assertNotNull(data); assertNotNull(data);
@ -89,10 +89,10 @@ class GrokServiceTest {
@Test @Test
@Disabled @Disabled
void messageStream() { void messageStream() {
String prompt = "给我一个KFC的广告词"; final String prompt = "给我一个KFC的广告词";
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
grokService.message(prompt, 4096, data -> { grokService.message(prompt, 4096, data -> {
assertNotNull(data); assertNotNull(data);
if (data.contains("[DONE]")) { if (data.contains("[DONE]")) {
@ -122,11 +122,11 @@ class GrokServiceTest {
@Disabled @Disabled
void testChatVisionStream() { void testChatVisionStream() {
final GrokService grokService = AIServiceFactory.getAIService(new AIConfigBuilder(ModelName.GROK.getValue()).setModel(Models.Grok.GROK_2_VISION_1212.getModel()).setApiKey(key).build(), GrokService.class); final GrokService grokService = AIServiceFactory.getAIService(new AIConfigBuilder(ModelName.GROK.getValue()).setModel(Models.Grok.GROK_2_VISION_1212.getModel()).setApiKey(key).build(), GrokService.class);
String prompt = "图片上有些什么?"; final String prompt = "图片上有些什么?";
List<String> images = List.of("https://img2.baidu.com/it/u=862000265,4064861820&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1544"); final List<String> images = List.of("https://img2.baidu.com/it/u=862000265,4064861820&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1544");
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
grokService.chatVision(prompt,images, data -> { grokService.chatVision(prompt,images, data -> {
assertNotNull(data); assertNotNull(data);
if (data.contains("[DONE]")) { if (data.contains("[DONE]")) {

View File

@ -52,9 +52,9 @@ class HutoolServiceTest {
@Test @Test
@Disabled @Disabled
void chatStream() { void chatStream() {
String prompt = "写一个疯狂星期四广告词"; final String prompt = "写一个疯狂星期四广告词";
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
hutoolService.chat(prompt, data -> { hutoolService.chat(prompt, data -> {
assertNotNull(data); assertNotNull(data);
@ -94,11 +94,11 @@ class HutoolServiceTest {
@Test @Test
@Disabled @Disabled
void testChatVisionStream() { void testChatVisionStream() {
String prompt = "图片上有些什么?"; final String prompt = "图片上有些什么?";
List<String> images = List.of("https://img2.baidu.com/it/u=862000265,4064861820&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1544"); final List<String> images = List.of("https://img2.baidu.com/it/u=862000265,4064861820&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1544");
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
hutoolService.chatVision(prompt,images, data -> { hutoolService.chatVision(prompt,images, data -> {
assertNotNull(data); assertNotNull(data);
if (data.contains("[DONE]")) { if (data.contains("[DONE]")) {
@ -160,7 +160,7 @@ class HutoolServiceTest {
final String filePath = "your filePath"; final String filePath = "your filePath";
FileUtil.writeFromStream(inputStream, new File(filePath)); FileUtil.writeFromStream(inputStream, new File(filePath));
} catch (Exception e) { } catch (final Exception e) {
throw new AIException("TTS测试失败: " + e.getMessage()); throw new AIException("TTS测试失败: " + e.getMessage());
} }

View File

@ -56,9 +56,9 @@ class OpenaiServiceTest {
@Test @Test
@Disabled @Disabled
void chatStream() { void chatStream() {
String prompt = "写一个疯狂星期四广告词"; final String prompt = "写一个疯狂星期四广告词";
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
openaiService.chat(prompt, data -> { openaiService.chat(prompt, data -> {
assertNotNull(data); assertNotNull(data);
@ -91,11 +91,11 @@ class OpenaiServiceTest {
void testChatVisionStream() { void testChatVisionStream() {
final OpenaiService openaiService = AIServiceFactory.getAIService(new AIConfigBuilder(ModelName.OPENAI.getValue()) final OpenaiService openaiService = AIServiceFactory.getAIService(new AIConfigBuilder(ModelName.OPENAI.getValue())
.setApiKey(key).setModel(Models.Openai.GPT_4O_MINI.getModel()).build(), OpenaiService.class); .setApiKey(key).setModel(Models.Openai.GPT_4O_MINI.getModel()).build(), OpenaiService.class);
String prompt = "图片上有些什么?"; final String prompt = "图片上有些什么?";
List<String> images = List.of("https://img2.baidu.com/it/u=862000265,4064861820&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1544\",\"https://img2.baidu.com/it/u=1682510685,1244554634&fm=253&fmt=auto&app=138&f=JPEG?w=803&h=800"); final List<String> images = List.of("https://img2.baidu.com/it/u=862000265,4064861820&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1544\",\"https://img2.baidu.com/it/u=1682510685,1244554634&fm=253&fmt=auto&app=138&f=JPEG?w=803&h=800");
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
openaiService.chatVision(prompt,images, data -> { openaiService.chatVision(prompt,images, data -> {
assertNotNull(data); assertNotNull(data);
if (data.contains("[DONE]")) { if (data.contains("[DONE]")) {
@ -226,7 +226,7 @@ class OpenaiServiceTest {
messages.add(new Message("user","给我一个KFC疯狂星期四的文案")); messages.add(new Message("user","给我一个KFC疯狂星期四的文案"));
// 使用AtomicBoolean作为结束标志 // 使用AtomicBoolean作为结束标志
AtomicBoolean isDone = new AtomicBoolean(false); final AtomicBoolean isDone = new AtomicBoolean(false);
openaiService.chatReasoning(messages,OpenaiCommon.OpenaiReasoning.HIGH.getEffort(), data -> { openaiService.chatReasoning(messages,OpenaiCommon.OpenaiReasoning.HIGH.getEffort(), data -> {
assertNotNull(data); assertNotNull(data);
if (data.contains("[DONE]")) { if (data.contains("[DONE]")) {

View File

@ -201,7 +201,7 @@ public class BeanUtil {
} }
// 先尝试直接获取属性 // 先尝试直接获取属性
if (bean instanceof Map<?, ?> map) { if (bean instanceof final Map<?, ?> map) {
if (map.containsKey(expression)) { if (map.containsKey(expression)) {
return (T) map.get(expression); return (T) map.get(expression);
} }

View File

@ -134,7 +134,7 @@ public class Number128 extends Number implements Comparable<Number128>{
if (this == o) { if (this == o) {
return true; return true;
} }
if (o instanceof Number128 number128) { if (o instanceof final Number128 number128) {
return leastSigBits == number128.leastSigBits && mostSigBits == number128.mostSigBits; return leastSigBits == number128.leastSigBits && mostSigBits == number128.mostSigBits;
} }
return false; return false;

View File

@ -1408,7 +1408,7 @@ public class CollUtil {
* @return 合并后的新列表 * @return 合并后的新列表
* @since 5.8.42 * @since 5.8.42
*/ */
public static <A, B, R> List<R> zip(Collection<A> collectionA, Collection<B> collectionB, BiFunction<A, B, R> zipper) { public static <A, B, R> List<R> zip(final Collection<A> collectionA, final Collection<B> collectionB, final BiFunction<A, B, R> zipper) {
if (CollUtil.isEmpty(collectionA) || CollUtil.isEmpty(collectionB)) { if (CollUtil.isEmpty(collectionA) || CollUtil.isEmpty(collectionB)) {
return new ArrayList<>(); return new ArrayList<>();
} }

View File

@ -88,7 +88,7 @@ public class SetUtil {
if (null == iterable) { if (null == iterable) {
return of(isLinked); return of(isLinked);
} }
if (iterable instanceof Collection<T> collection) { if (iterable instanceof final Collection<T> collection) {
return isLinked ? new LinkedHashSet<>(collection) : new HashSet<>(collection); return isLinked ? new LinkedHashSet<>(collection) : new HashSet<>(collection);
} }
return of(isLinked, iterable.iterator()); return of(isLinked, iterable.iterator());

View File

@ -182,14 +182,14 @@ public class ArrayConverter extends AbstractConverter implements MatcherConverte
*/ */
private Object convertIterableToArray(final Class<?> targetComponentType, final Iterable<?> value) { private Object convertIterableToArray(final Class<?> targetComponentType, final Iterable<?> value) {
final Object result; final Object result;
if (value instanceof List<?> list) { if (value instanceof final List<?> list) {
// List转数组 // List转数组
final int size = list.size(); final int size = list.size();
result = Array.newInstance(targetComponentType, size); result = Array.newInstance(targetComponentType, size);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
Array.set(result, i, convertComponentType(targetComponentType, list.get(i))); Array.set(result, i, convertComponentType(targetComponentType, list.get(i)));
} }
} else if (value instanceof Collection<?> collection) { } else if (value instanceof final Collection<?> collection) {
// 集合转数组 // 集合转数组
result = Array.newInstance(targetComponentType, collection.size()); result = Array.newInstance(targetComponentType, collection.size());

View File

@ -89,14 +89,14 @@ public class EntryConverter extends ConverterWithRoot implements MatcherConverte
public Map.Entry<?, ?> convert(final Type targetType, final Type keyType, final Type valueType, final Object value) public Map.Entry<?, ?> convert(final Type targetType, final Type keyType, final Type valueType, final Object value)
throws ConvertException { throws ConvertException {
Map map = null; Map map = null;
if (value instanceof Map.Entry entry) { if (value instanceof final Map.Entry entry) {
map = MapUtil.of(entry.getKey(), entry.getValue()); map = MapUtil.of(entry.getKey(), entry.getValue());
} else if (value instanceof Pair) { } else if (value instanceof Pair) {
final Pair entry = (Pair<?, ?>) value; final Pair entry = (Pair<?, ?>) value;
map = MapUtil.of(entry.getLeft(), entry.getRight()); map = MapUtil.of(entry.getLeft(), entry.getRight());
} else if (value instanceof Map) { } else if (value instanceof Map) {
map = (Map) value; map = (Map) value;
} else if (value instanceof CharSequence str) { } else if (value instanceof final CharSequence str) {
map = strToMap(str); map = strToMap(str);
} else if (BeanUtil.isWritableBean(value.getClass())) { } else if (BeanUtil.isWritableBean(value.getClass())) {
// 一次性只读场景包装为Map效率更高 // 一次性只读场景包装为Map效率更高

View File

@ -80,14 +80,14 @@ public class PairConverter extends ConverterWithRoot implements Serializable {
public Pair<?, ?> convert(final Type leftType, final Type rightType, final Object value) public Pair<?, ?> convert(final Type leftType, final Type rightType, final Object value)
throws ConvertException { throws ConvertException {
Map map = null; Map map = null;
if (value instanceof Map.Entry entry) { if (value instanceof final Map.Entry entry) {
map = MapUtil.of(entry.getKey(), entry.getValue()); map = MapUtil.of(entry.getKey(), entry.getValue());
} else if (value instanceof Pair) { } else if (value instanceof Pair) {
final Pair entry = (Pair<?, ?>) value; final Pair entry = (Pair<?, ?>) value;
map = MapUtil.of(entry.getLeft(), entry.getRight()); map = MapUtil.of(entry.getLeft(), entry.getRight());
} else if (value instanceof Map) { } else if (value instanceof Map) {
map = (Map) value; map = (Map) value;
} else if (value instanceof CharSequence str) { } else if (value instanceof final CharSequence str) {
map = strToMap(str); map = strToMap(str);
} else if (BeanUtil.isReadableBean(value.getClass())) { } else if (BeanUtil.isReadableBean(value.getClass())) {
// 一次性只读场景包装为Map效率更高 // 一次性只读场景包装为Map效率更高

View File

@ -36,7 +36,7 @@ public class StackTraceElementConverter extends AbstractConverter {
@Override @Override
protected StackTraceElement convertInternal(final Class<?> targetClass, final Object value) { protected StackTraceElement convertInternal(final Class<?> targetClass, final Object value) {
if (value instanceof Map<?, ?> map) { if (value instanceof final Map<?, ?> map) {
final String declaringClass = MapUtil.getStr(map, "className"); final String declaringClass = MapUtil.getStr(map, "className");
final String methodName = MapUtil.getStr(map, "methodName"); final String methodName = MapUtil.getStr(map, "methodName");

View File

@ -110,7 +110,7 @@ public class TemporalAccessorConverter extends AbstractConverter {
} else if (value instanceof Date) { } else if (value instanceof Date) {
final DateTime dateTime = DateUtil.date((Date) value); final DateTime dateTime = DateUtil.date((Date) value);
return parseFromInstant(targetClass, dateTime.toInstant(), dateTime.getZoneId()); return parseFromInstant(targetClass, dateTime.toInstant(), dateTime.getZoneId());
} else if (value instanceof Calendar calendar) { } else if (value instanceof final Calendar calendar) {
return parseFromInstant(targetClass, calendar.toInstant(), calendar.getTimeZone().toZoneId()); return parseFromInstant(targetClass, calendar.toInstant(), calendar.getTimeZone().toZoneId());
} else { } else {
return parseFromCharSequence(targetClass, convertToStr(value)); return parseFromCharSequence(targetClass, convertToStr(value));

View File

@ -87,7 +87,7 @@ public class XMLGregorianCalendarConverter extends AbstractConverter {
// Handle Date // Handle Date
if (value instanceof Date) { if (value instanceof Date) {
gregorianCalendar.setTime((Date) value); gregorianCalendar.setTime((Date) value);
} else if (value instanceof Calendar calendar) { } else if (value instanceof final Calendar calendar) {
gregorianCalendar.setTimeZone(calendar.getTimeZone()); gregorianCalendar.setTimeZone(calendar.getTimeZone());
gregorianCalendar.setFirstDayOfWeek(calendar.getFirstDayOfWeek()); gregorianCalendar.setFirstDayOfWeek(calendar.getFirstDayOfWeek());
gregorianCalendar.setLenient(calendar.isLenient()); gregorianCalendar.setLenient(calendar.isLenient());

View File

@ -348,18 +348,7 @@ public class DatePattern {
* Inner class to output a constant single character. * Inner class to output a constant single character.
* </p> * </p>
*/ */
private static class CharacterLiteral implements Rule { private record CharacterLiteral(char mValue) implements Rule {
private final char mValue;
/**
* Constructs a new instance of {@code CharacterLiteral} to hold the specified value.
*
* @param value the character literal
*/
CharacterLiteral(final char value) {
mValue = value;
}
@Override @Override
public int estimateLength() { public int estimateLength() {
return 1; return 1;
@ -376,18 +365,7 @@ public class DatePattern {
* Inner class to output a constant string. * Inner class to output a constant string.
* </p> * </p>
*/ */
private static class StringLiteral implements Rule { private record StringLiteral(String mValue) implements Rule {
private final String mValue;
/**
* Constructs a new instance of {@code StringLiteral} to hold the specified value.
*
* @param value the string literal
*/
StringLiteral(final String value) {
mValue = value;
}
@Override @Override
public int estimateLength() { public int estimateLength() {
return mValue.length(); return mValue.length();
@ -404,21 +382,7 @@ public class DatePattern {
* Inner class to output one of a set of values. * Inner class to output one of a set of values.
* </p> * </p>
*/ */
private static class TextField implements Rule { private record TextField(int mField, String[] mValues) implements Rule {
private final int mField;
private final String[] mValues;
/**
* Constructs an instance of {@code TextField} with the specified field and values.
*
* @param field the field
* @param values the field values
*/
TextField(final int field, final String[] values) {
mField = field;
mValues = values;
}
@Override @Override
public int estimateLength() { public int estimateLength() {
int max = 0; int max = 0;
@ -431,6 +395,7 @@ public class DatePattern {
return max; return max;
} }
@SuppressWarnings("MagicConstant")
@Override @Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
buffer.append(mValues[calendar.get(mField)]); buffer.append(mValues[calendar.get(mField)]);
@ -442,23 +407,14 @@ public class DatePattern {
* Inner class to output an unpadded number. * Inner class to output an unpadded number.
* </p> * </p>
*/ */
private static class UnpaddedNumberField implements NumberRule { private record UnpaddedNumberField(int mField) implements NumberRule {
private final int mField;
/**
* Constructs an instance of {@code UnpadedNumberField} with the specified field.
*
* @param field the field
*/
UnpaddedNumberField(final int field) {
mField = field;
}
@Override @Override
public int estimateLength() { public int estimateLength() {
return 4; return 4;
} }
@SuppressWarnings("MagicConstant")
@Override @Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
appendTo(buffer, calendar.get(mField)); appendTo(buffer, calendar.get(mField));
@ -515,23 +471,18 @@ public class DatePattern {
* Inner class to output a padded number. * Inner class to output a padded number.
* </p> * </p>
*/ */
private static class PaddedNumberField implements NumberRule { private record PaddedNumberField(int mField, int mSize) implements NumberRule {
private final int mField;
private final int mSize;
/** /**
* Constructs an instance of {@code PaddedNumberField}. * Constructs an instance of {@code PaddedNumberField}.
* *
* @param field the field * @param mField the field
* @param size size of the output field * @param mSize size of the output field
*/ */
PaddedNumberField(final int field, final int size) { private PaddedNumberField {
if (size < 3) { if (mSize < 3) {
// Should use UnpaddedNumberField or TwoDigitNumberField. // Should use UnpaddedNumberField or TwoDigitNumberField.
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
mField = field;
mSize = size;
} }
@Override @Override
@ -539,6 +490,7 @@ public class DatePattern {
return mSize; return mSize;
} }
@SuppressWarnings("MagicConstant")
@Override @Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
appendTo(buffer, calendar.get(mField)); appendTo(buffer, calendar.get(mField));
@ -555,23 +507,13 @@ public class DatePattern {
* Inner class to output a two digit number. * Inner class to output a two digit number.
* </p> * </p>
*/ */
private static class TwoDigitNumberField implements NumberRule { private record TwoDigitNumberField(int mField) implements NumberRule {
private final int mField;
/**
* Constructs an instance of {@code TwoDigitNumberField} with the specified field.
*
* @param field the field
*/
TwoDigitNumberField(final int field) {
mField = field;
}
@Override @Override
public int estimateLength() { public int estimateLength() {
return 2; return 2;
} }
@SuppressWarnings("MagicConstant")
@Override @Override
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
appendTo(buffer, calendar.get(mField)); appendTo(buffer, calendar.get(mField));
@ -652,18 +594,7 @@ public class DatePattern {
* Inner class to output the twelve hour field. * Inner class to output the twelve hour field.
* </p> * </p>
*/ */
private static class TwelveHourField implements NumberRule { private record TwelveHourField(NumberRule mRule) implements NumberRule {
private final NumberRule mRule;
/**
* Constructs an instance of {@code TwelveHourField} with the specified {@code NumberRule}.
*
* @param rule the rule
*/
TwelveHourField(final NumberRule rule) {
mRule = rule;
}
@Override @Override
public int estimateLength() { public int estimateLength() {
return mRule.estimateLength(); return mRule.estimateLength();
@ -685,22 +616,9 @@ public class DatePattern {
} }
/** /**
* <p>
* Inner class to output the twenty four hour field. * Inner class to output the twenty four hour field.
* </p>
*/ */
private static class TwentyFourHourField implements NumberRule { private record TwentyFourHourField(NumberRule mRule) implements NumberRule {
private final NumberRule mRule;
/**
* Constructs an instance of {@code TwentyFourHourField} with the specified {@code NumberRule}.
*
* @param rule the rule
*/
TwentyFourHourField(final NumberRule rule) {
mRule = rule;
}
@Override @Override
public int estimateLength() { public int estimateLength() {
return mRule.estimateLength(); return mRule.estimateLength();
@ -722,17 +640,9 @@ public class DatePattern {
} }
/** /**
* <p>
* Inner class to output the numeric day in week. * Inner class to output the numeric day in week.
* </p>
*/ */
private static class DayInWeekField implements NumberRule { private record DayInWeekField(NumberRule mRule) implements NumberRule {
private final NumberRule mRule;
DayInWeekField(final NumberRule rule) {
mRule = rule;
}
@Override @Override
public int estimateLength() { public int estimateLength() {
return mRule.estimateLength(); return mRule.estimateLength();
@ -751,17 +661,9 @@ public class DatePattern {
} }
/** /**
* <p>
* Inner class to output the numeric day in week. * Inner class to output the numeric day in week.
* </p>
*/ */
private static class WeekYear implements NumberRule { private record WeekYear(NumberRule mRule) implements NumberRule {
private final NumberRule mRule;
WeekYear(final NumberRule rule) {
mRule = rule;
}
@Override @Override
public int estimateLength() { public int estimateLength() {
return mRule.estimateLength(); return mRule.estimateLength();
@ -784,9 +686,7 @@ public class DatePattern {
} }
/** /**
* <p>
* Inner class to output a time zone name. * Inner class to output a time zone name.
* </p>
*/ */
private static class TimeZoneNameRule implements Rule { private static class TimeZoneNameRule implements Rule {
private final Locale mLocale; private final Locale mLocale;
@ -829,25 +729,12 @@ public class DatePattern {
} }
/** /**
* <p>
* Inner class to output a time zone as a number {@code +/-HHMM} or {@code +/-HH:MM}. * Inner class to output a time zone as a number {@code +/-HHMM} or {@code +/-HH:MM}.
* </p>
*/ */
private static class TimeZoneNumberRule implements Rule { private record TimeZoneNumberRule(boolean mColon) implements Rule {
static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true); static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true);
static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false); static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false);
final boolean mColon;
/**
* Constructs an instance of {@code TimeZoneNumberRule} with the specified properties.
*
* @param colon add colon between HH and MM in the output if {@code true}
*/
TimeZoneNumberRule(final boolean colon) {
mColon = colon;
}
@Override @Override
public int estimateLength() { public int estimateLength() {
return 5; return 5;
@ -882,7 +769,7 @@ public class DatePattern {
* Inner class to output a time zone as a number {@code +/-HHMM} or {@code +/-HH:MM}. * Inner class to output a time zone as a number {@code +/-HHMM} or {@code +/-HH:MM}.
* </p> * </p>
*/ */
private static class Iso8601_Rule implements Rule { private record Iso8601_Rule(int length) implements Rule {
// Sign TwoDigitHours or Z // Sign TwoDigitHours or Z
static final Iso8601_Rule ISO8601_HOURS = new Iso8601_Rule(3); static final Iso8601_Rule ISO8601_HOURS = new Iso8601_Rule(3);
@ -906,15 +793,12 @@ public class DatePattern {
}; };
} }
final int length;
/** /**
* Constructs an instance of {@code Iso8601_Rule} with the specified properties. * Constructs an instance of {@code Iso8601_Rule} with the specified properties.
* *
* @param length The number of characters in output (unless Z is output) * @param length The number of characters in output (unless Z is output)
*/ */
Iso8601_Rule(final int length) { private Iso8601_Rule {
this.length = length;
} }
@Override @Override
@ -1103,7 +987,7 @@ public class DatePattern {
if (this == obj) { if (this == obj) {
return true; return true;
} }
if (obj instanceof TimeZoneDisplayKey other) { if (obj instanceof final TimeZoneDisplayKey other) {
return mTimeZone.equals(other.mTimeZone) && mStyle == other.mStyle && mLocale.equals(other.mLocale); return mTimeZone.equals(other.mTimeZone) && mStyle == other.mStyle && mLocale.equals(other.mLocale);
} }
return false; return false;

View File

@ -436,7 +436,7 @@ public class FastDateFormat extends Format implements PositionDateParser, DatePr
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@Override @Override
public boolean equals(final Object obj) { public boolean equals(final Object obj) {
if (!(obj instanceof FastDateFormat other)) { if (!(obj instanceof final FastDateFormat other)) {
return false; return false;
} }
// no need to check parser, as it has same invariants as printer // no need to check parser, as it has same invariants as printer

View File

@ -75,7 +75,7 @@ public class SimpleDateBasic implements DateBasic, Serializable {
// ----------------------------------------------------------------------- Basics // ----------------------------------------------------------------------- Basics
@Override @Override
public boolean equals(final Object obj) { public boolean equals(final Object obj) {
if (!(obj instanceof FastDatePrinter other)) { if (!(obj instanceof final FastDatePrinter other)) {
return false; return false;
} }
return pattern.equals(other.pattern) && timeZone.equals(other.timeZone) && locale.equals(other.locale); return pattern.equals(other.pattern) && timeZone.equals(other.timeZone) && locale.equals(other.locale);

View File

@ -55,7 +55,7 @@ public class ManifestUtil {
throw new IORuntimeException(e); throw new IORuntimeException(e);
} }
if (connection instanceof JarURLConnection conn) { if (connection instanceof final JarURLConnection conn) {
return getManifest(conn); return getManifest(conn);
} }
return null; return null;

View File

@ -89,7 +89,7 @@ public class JarResource extends UrlResource {
*/ */
private JarFile doGetJarFile() throws IOException { private JarFile doGetJarFile() throws IOException {
final URLConnection con = getUrl().openConnection(); final URLConnection con = getUrl().openConnection();
if (con instanceof JarURLConnection jarCon) { if (con instanceof final JarURLConnection jarCon) {
return jarCon.getJarFile(); return jarCon.getJarFile();
} else { } else {
final String urlFile = getUrl().getFile(); final String urlFile = getUrl().getFile();

View File

@ -127,7 +127,7 @@ public class ResourceFinder {
String rootEntryPath; String rootEntryPath;
final boolean closeJarFile; final boolean closeJarFile;
if (conn instanceof JarURLConnection jarCon) { if (conn instanceof final JarURLConnection jarCon) {
UrlUtil.useCachesIfNecessary(jarCon); UrlUtil.useCachesIfNecessary(jarCon);
jarFile = jarCon.getJarFile(); jarFile = jarCon.getJarFile();
final JarEntry jarEntry = jarCon.getJarEntry(); final JarEntry jarEntry = jarCon.getJarEntry();

View File

@ -52,7 +52,7 @@ public class Console {
* @param obj 要打印的对象 * @param obj 要打印的对象
*/ */
public static void log(final Object obj) { public static void log(final Object obj) {
if (obj instanceof Throwable e) { if (obj instanceof final Throwable e) {
log(e, e.getMessage()); log(e, e.getMessage());
} else { } else {
log(TEMPLATE_VAR, obj); log(TEMPLATE_VAR, obj);
@ -219,7 +219,7 @@ public class Console {
* @param obj 要打印的对象 * @param obj 要打印的对象
*/ */
public static void error(final Object obj) { public static void error(final Object obj) {
if (obj instanceof Throwable e) { if (obj instanceof final Throwable e) {
error(e, e.getMessage()); error(e, e.getMessage());
} else { } else {
error(TEMPLATE_VAR, obj); error(TEMPLATE_VAR, obj);

View File

@ -541,7 +541,7 @@ public class Opt<T> {
return true; return true;
} }
if (!(obj instanceof Opt<?> other)) { if (!(obj instanceof final Opt<?> other)) {
return false; return false;
} }

View File

@ -82,7 +82,7 @@ public class Triple<L, M, R> extends Pair<L, R> {
if (this == o) { if (this == o) {
return true; return true;
} }
if (o instanceof Triple<?, ?, ?> triple) { if (o instanceof final Triple<?, ?, ?> triple) {
return Objects.equals(getLeft(), triple.getLeft()) && return Objects.equals(getLeft(), triple.getLeft()) &&
Objects.equals(getMiddle(), triple.getMiddle()) && Objects.equals(getMiddle(), triple.getMiddle()) &&
Objects.equals(getRight(), triple.getRight()); Objects.equals(getRight(), triple.getRight());

View File

@ -39,7 +39,7 @@ public abstract class AbsEntry<K, V> implements Map.Entry<K, V> {
@Override @Override
public boolean equals(final Object object) { public boolean equals(final Object object) {
if (object instanceof Map.Entry<?, ?> that) { if (object instanceof final Map.Entry<?, ?> that) {
return ObjUtil.equals(this.getKey(), that.getKey()) return ObjUtil.equals(this.getKey(), that.getKey())
&& ObjUtil.equals(this.getValue(), that.getValue()); && ObjUtil.equals(this.getValue(), that.getValue());
} }

View File

@ -54,7 +54,7 @@ public abstract class AbsTable<R, C, V> implements Table<R, C, V> {
public boolean equals(final Object obj) { public boolean equals(final Object obj) {
if (obj == this) { if (obj == this) {
return true; return true;
} else if (obj instanceof Table<?, ?, ?> that) { } else if (obj instanceof final Table<?, ?, ?> that) {
return this.cellSet().equals(that.cellSet()); return this.cellSet().equals(that.cellSet());
} else { } else {
return false; return false;
@ -231,7 +231,7 @@ public abstract class AbsTable<R, C, V> implements Table<R, C, V> {
if (obj == this) { if (obj == this) {
return true; return true;
} }
if (obj instanceof Cell<?, ?, ?> other) { if (obj instanceof final Cell<?, ?, ?> other) {
return ObjUtil.equals(rowKey, other.getRowKey()) return ObjUtil.equals(rowKey, other.getRowKey())
&& ObjUtil.equals(columnKey, other.getColumnKey()) && ObjUtil.equals(columnKey, other.getColumnKey())
&& ObjUtil.equals(value, other.getValue()); && ObjUtil.equals(value, other.getValue());

View File

@ -161,7 +161,7 @@ public class ChineseNumberFormatter {
public String format(final BigDecimal amount) { public String format(final BigDecimal amount) {
final long longValue = amount.longValue(); final long longValue = amount.longValue();
String formatAmount; final String formatAmount;
if (amount.scale() <= 0) { if (amount.scale() <= 0) {
formatAmount = format(longValue); formatAmount = format(longValue);
} else { } else {

View File

@ -618,7 +618,7 @@ public final class Fraction extends Number implements Comparable<Fraction> {
if (obj == this) { if (obj == this) {
return true; return true;
} }
if (!(obj instanceof Fraction other)) { if (!(obj instanceof final Fraction other)) {
return false; return false;
} }
return getNumerator() == other.getNumerator() && getDenominator() == other.getDenominator(); return getNumerator() == other.getNumerator() && getDenominator() == other.getDenominator();

View File

@ -662,7 +662,7 @@ public class UrlUtil {
try { try {
conn = url.openConnection(); conn = url.openConnection();
useCachesIfNecessary(conn); useCachesIfNecessary(conn);
if (conn instanceof HttpURLConnection httpCon) { if (conn instanceof final HttpURLConnection httpCon) {
httpCon.setRequestMethod("HEAD"); httpCon.setRequestMethod("HEAD");
} }
return conn.getContentLengthLong(); return conn.getContentLengthLong();

View File

@ -60,7 +60,7 @@ public class MethodTypeUtil {
if (null == declaringClass) { if (null == declaringClass) {
declaringClass = executable.getDeclaringClass(); declaringClass = executable.getDeclaringClass();
} }
if (executable instanceof Method method) { if (executable instanceof final Method method) {
return MethodType.methodType(method.getReturnType(), declaringClass, method.getParameterTypes()); return MethodType.methodType(method.getReturnType(), declaringClass, method.getParameterTypes());
} else { } else {
final Constructor<?> constructor = (Constructor<?>) executable; final Constructor<?> constructor = (Constructor<?>) executable;

View File

@ -57,7 +57,7 @@ public class JdkServiceLoaderUtil {
break; break;
} }
instance = iterator.next(); instance = iterator.next();
} catch (ServiceConfigurationError | NoClassDefFoundError e) { } catch (final ServiceConfigurationError | NoClassDefFoundError e) {
// 安全忽略当前实现尝试下一个 // 安全忽略当前实现尝试下一个
continue; continue;
} }

View File

@ -2416,8 +2416,25 @@ public class CharSequenceUtil extends StrValidator {
if (null == str1 || null == str2) { if (null == str1 || null == str2) {
return false; return false;
} }
if (str1 instanceof String && str2 instanceof String) {
return ((String) str1).regionMatches(ignoreCase, offset1, (String) str2, offset2, length);
}
// pr#4134@Github
// CharSequence StringBuilder 类时会发生拷贝效率很低而且复杂度会退化至 O(N^2)这里直接手动匹配
if (offset1 < 0 || offset2 < 0 || length < 0) {
return false;
}
if (str1.length() - offset1 < length || str2.length() - offset2 < length) {
return false;
}
for (int i = 0; i < length; i++) {
if (CharUtil.equals(str1.charAt(offset1 + i), str2.charAt(offset2 + i), ignoreCase)) {
continue;
}
return false;
}
return str1.toString().regionMatches(ignoreCase, offset1, str2.toString(), offset2, length); return true;
} }
// endregion // endregion
@ -3954,7 +3971,7 @@ public class CharSequenceUtil extends StrValidator {
* @return StringBuilder对象 * @return StringBuilder对象
* @since 5.8.42 * @since 5.8.42
*/ */
public static StringBuilder builder(Function<CharSequence, CharSequence> strEditor, final CharSequence... strs){ public static StringBuilder builder(final Function<CharSequence, CharSequence> strEditor, final CharSequence... strs){
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
for (final CharSequence str : strs) { for (final CharSequence str : strs) {
sb.append(strEditor.apply( str)); sb.append(strEditor.apply( str));

View File

@ -236,7 +236,7 @@ public class StrJoiner implements Appendable, Serializable {
append((Iterator<?>) obj); append((Iterator<?>) obj);
} else if (obj instanceof Iterable) { } else if (obj instanceof Iterable) {
append(((Iterable<?>) obj).iterator()); append(((Iterable<?>) obj).iterator());
}else if (obj instanceof Map.Entry<?, ?> entry) { }else if (obj instanceof final Map.Entry<?, ?> entry) {
append(entry.getKey()).append(entry.getValue()); append(entry.getKey()).append(entry.getValue());
} else { } else {
append(ConvertUtil.toStr(obj)); append(ConvertUtil.toStr(obj));
@ -448,7 +448,7 @@ public class StrJoiner implements Appendable, Serializable {
* @param appendable {@link Appendable} * @param appendable {@link Appendable}
*/ */
private void checkHasContent(final Appendable appendable) { private void checkHasContent(final Appendable appendable) {
if (appendable instanceof CharSequence charSequence) { if (appendable instanceof final CharSequence charSequence) {
if (!charSequence.isEmpty() && StrUtil.endWith(charSequence, delimiter)) { if (!charSequence.isEmpty() && StrUtil.endWith(charSequence, delimiter)) {
this.hasContent = true; this.hasContent = true;
} }

View File

@ -17,9 +17,12 @@
package cn.hutool.v7.core.text.finder; package cn.hutool.v7.core.text.finder;
import cn.hutool.v7.core.lang.Assert; import cn.hutool.v7.core.lang.Assert;
import cn.hutool.v7.core.text.CharSequenceUtil;
import java.io.Serial; import java.io.Serial;
import java.util.HashMap;
import java.util.Map;
import static cn.hutool.v7.core.text.CharSequenceUtil.isSubEquals;
/** /**
* 字符串查找器 * 字符串查找器
@ -44,6 +47,8 @@ public class StrFinder extends TextFinder {
private final CharSequence strToFind; private final CharSequence strToFind;
private final boolean caseInsensitive; private final boolean caseInsensitive;
private Map<Character, Integer> forwardOffsetMap;
private Map<Character, Integer> reverseOffsetMap;
/** /**
* 构造 * 构造
@ -61,23 +66,55 @@ public class StrFinder extends TextFinder {
public int start(int from) { public int start(int from) {
Assert.notNull(this.text, "Text to find must be not null!"); Assert.notNull(this.text, "Text to find must be not null!");
final int subLen = strToFind.length(); final int subLen = strToFind.length();
final int textLen = text.length();
// pr#4134@github
// 基于Sunday算法实现高效子串查询理想情况为O(N / M)最差情况(大量重复元素)会退化至O(M * N)一般情况下优于 KMP算法任何情况下都优于原来的暴力算法
if (negative) {
if (this.reverseOffsetMap == null) {
this.reverseOffsetMap = buildReverseOffsetMap(strToFind, caseInsensitive);
}
final int maxIndex = textLen - subLen;
if (from > maxIndex) {
from = maxIndex;
}
int i = from;
while (i >= 0) {
if (isSubEquals(text, i, strToFind, 0, subLen, caseInsensitive)) {
return i;
}
if (i - 1 < 0) {
break;
}
final char preChar = text.charAt(i - 1);
final int jump = reverseOffsetMap.getOrDefault(
caseInsensitive ? Character.toLowerCase(preChar) : preChar,
subLen + 1
);
i -= jump;
}
} else {
if (this.forwardOffsetMap == null) {
this.forwardOffsetMap = buildForwardOffsetMap(strToFind, caseInsensitive);
}
if (from < 0) { if (from < 0) {
from = 0; from = 0;
} }
int endLimit = getValidEndIndex(); final int endLimit = textLen - subLen;
if (negative) { int i = from;
for (int i = from; i > endLimit; i--) { while (i <= endLimit) {
if (CharSequenceUtil.isSubEquals(text, i, strToFind, 0, subLen, caseInsensitive)) { if (isSubEquals(text, i, strToFind, 0, subLen, caseInsensitive)) {
return i; return i;
} }
if (i + subLen >= textLen) {
break;
} }
} else { final char nextChar = text.charAt(i + subLen);
endLimit = endLimit - subLen + 1; final int jump = forwardOffsetMap.getOrDefault(
for (int i = from; i < endLimit; i++) { caseInsensitive ? Character.toLowerCase(nextChar) : nextChar,
if (CharSequenceUtil.isSubEquals(text, i, strToFind, 0, subLen, caseInsensitive)) { subLen + 1
return i; );
} i += jump;
} }
} }
@ -91,4 +128,44 @@ public class StrFinder extends TextFinder {
} }
return start + strToFind.length(); return start + strToFind.length();
} }
/**
* 构建正向偏移表
*/
private static Map<Character, Integer> buildForwardOffsetMap(final CharSequence pattern, final boolean caseInsensitive) {
final int m = pattern.length();
final Map<Character, Integer> map = new HashMap<>(Math.min(m, 128));
for (int i = 0; i < m; i++) {
final char c = pattern.charAt(i);
final int jump = m - i;
if (caseInsensitive) {
map.put(Character.toLowerCase(c), jump);
} else {
map.put(c, jump);
}
}
return map;
}
/**
* 构建反向偏移表
*/
private static Map<Character, Integer> buildReverseOffsetMap(final CharSequence pattern, final boolean caseInsensitive) {
final int m = pattern.length();
final Map<Character, Integer> map = new HashMap<>(Math.min(m, 128));
for (int i = m - 1; i >= 0; i--) {
final char c = pattern.charAt(i);
final int jump = i + 1;
if (caseInsensitive) {
map.put(Character.toLowerCase(c), jump);
} else {
map.put(c, jump);
}
}
return map;
}
} }

View File

@ -795,9 +795,9 @@ public class ThreadUtil {
* @since 4.5.8 * @since 4.5.8
*/ */
public static ConcurrencyTester concurrencyTest(final int threadSize, final Runnable runnable) { public static ConcurrencyTester concurrencyTest(final int threadSize, final Runnable runnable) {
try (ConcurrencyTester tester = new ConcurrencyTester(threadSize)) { try (final ConcurrencyTester tester = new ConcurrencyTester(threadSize)) {
return tester.test(runnable); return tester.test(runnable);
} catch (IOException e) { } catch (final IOException e) {
throw new IORuntimeException(e); throw new IORuntimeException(e);
} }
} }

View File

@ -1022,20 +1022,20 @@ public class BeanUtilTest {
@Test @Test
void checkBean_withNullBean_shouldReturnTrue() { void checkBean_withNullBean_shouldReturnTrue() {
Predicate<Field> predicate = field -> true; final Predicate<Field> predicate = field -> true;
assertTrue(BeanUtil.checkBean(null, predicate)); assertTrue(BeanUtil.checkBean(null, predicate));
} }
@Test @Test
void checkBean_withNoMatchingFields_shouldReturnFalse() { void checkBean_withNoMatchingFields_shouldReturnFalse() {
Person bean = new Person(); final Person bean = new Person();
Predicate<Field> predicate = field -> false; final Predicate<Field> predicate = field -> false;
assertFalse(BeanUtil.checkBean(bean, predicate)); assertFalse(BeanUtil.checkBean(bean, predicate));
} }
@Test @Test
void checkBean_withMatchingField_shouldReturnTrue() { void checkBean_withMatchingField_shouldReturnTrue() {
Person bean = new Person(); final Person bean = new Person();
Predicate<Field> predicate = field -> "name".equals(field.getName()); Predicate<Field> predicate = field -> "name".equals(field.getName());
assertTrue(BeanUtil.checkBean(bean, predicate)); assertTrue(BeanUtil.checkBean(bean, predicate));
@ -1046,12 +1046,12 @@ public class BeanUtilTest {
@Test @Test
void findEditor_shouldReturnEditorForRegisteredType() { void findEditor_shouldReturnEditorForRegisteredType() {
// Given // Given
Class<?> type = Integer.class; final Class<?> type = Integer.class;
// Register editor for Integer if not already registered (though usually it's pre-registered) // Register editor for Integer if not already registered (though usually it's pre-registered)
PropertyEditor expectedEditor = PropertyEditorManager.findEditor(type); final PropertyEditor expectedEditor = PropertyEditorManager.findEditor(type);
// When // When
PropertyEditor actualEditor = BeanUtil.findEditor(type); final PropertyEditor actualEditor = BeanUtil.findEditor(type);
// Then // Then
assertNotNull(actualEditor); assertNotNull(actualEditor);
@ -1062,10 +1062,10 @@ public class BeanUtilTest {
void findEditor_shouldReturnNullForUnregisteredType() { void findEditor_shouldReturnNullForUnregisteredType() {
// Given // Given
class CustomUnregisteredType {} class CustomUnregisteredType {}
Class<?> type = CustomUnregisteredType.class; final Class<?> type = CustomUnregisteredType.class;
// When // When
PropertyEditor editor = BeanUtil.findEditor(type); final PropertyEditor editor = BeanUtil.findEditor(type);
// Then // Then
assertNull(editor); assertNull(editor);
@ -1074,10 +1074,10 @@ public class BeanUtilTest {
@Test @Test
void findEditor_shouldHandlePrimitiveTypes() { void findEditor_shouldHandlePrimitiveTypes() {
// Given // Given
Class<?> type = int.class; final Class<?> type = int.class;
// When // When
PropertyEditor editor = BeanUtil.findEditor(type); final PropertyEditor editor = BeanUtil.findEditor(type);
// Then // Then
assertNotNull(editor); assertNotNull(editor);
@ -1085,7 +1085,7 @@ public class BeanUtilTest {
@Test @Test
void descForEach_shouldProcessAllProperties() { void descForEach_shouldProcessAllProperties() {
List<String> processedProperties = new ArrayList<>(); final List<String> processedProperties = new ArrayList<>();
// 执行 // 执行
BeanUtil.descForEach(Person.class, propDesc -> processedProperties.add(propDesc.getFieldName())); BeanUtil.descForEach(Person.class, propDesc -> processedProperties.add(propDesc.getFieldName()));
@ -1099,7 +1099,7 @@ public class BeanUtilTest {
@Test @Test
public void testIsMatchName_SimpleMatch() { public void testIsMatchName_SimpleMatch() {
String testObj = "test"; final String testObj = "test";
assertTrue(BeanUtil.isMatchName(testObj, "String", true)); assertTrue(BeanUtil.isMatchName(testObj, "String", true));
assertTrue(BeanUtil.isMatchName(testObj, "string", true)); assertTrue(BeanUtil.isMatchName(testObj, "string", true));
@ -1110,7 +1110,7 @@ public class BeanUtilTest {
@Test @Test
public void testIsMatchName_FullMatch() { public void testIsMatchName_FullMatch() {
Integer testObj = 123; final Integer testObj = 123;
assertTrue(BeanUtil.isMatchName(testObj, "java.lang.Integer", false)); assertTrue(BeanUtil.isMatchName(testObj, "java.lang.Integer", false));
assertFalse(BeanUtil.isMatchName(testObj, "Integer", false)); assertFalse(BeanUtil.isMatchName(testObj, "Integer", false));
@ -1120,7 +1120,7 @@ public class BeanUtilTest {
@Test @Test
void testGetPropertyDescriptor_ExistingField() { void testGetPropertyDescriptor_ExistingField() {
PropertyDescriptor pd = BeanUtil.getPropertyDescriptor(Person.class, "name"); final PropertyDescriptor pd = BeanUtil.getPropertyDescriptor(Person.class, "name");
assertNotNull(pd); assertNotNull(pd);
assertEquals("name", pd.getName()); assertEquals("name", pd.getName());
assertEquals(String.class, pd.getPropertyType()); assertEquals(String.class, pd.getPropertyType());
@ -1134,7 +1134,7 @@ public class BeanUtilTest {
@Test @Test
void testBeanToMap_IgnoreNullValue() { void testBeanToMap_IgnoreNullValue() {
Person person = new Person(); final Person person = new Person();
person.setName(null); person.setName(null);
person.setAge(25); person.setAge(25);

View File

@ -36,8 +36,8 @@ public class DynaBeanTest {
@Test @Test
void createDynaBean_withPlainObject_shouldReturnDynaBean() { void createDynaBean_withPlainObject_shouldReturnDynaBean() {
BeanUtilTest.Person bean = new BeanUtilTest.Person(); final BeanUtilTest.Person bean = new BeanUtilTest.Person();
DynaBean dynaBean = BeanUtil.createDynaBean(bean); final DynaBean dynaBean = BeanUtil.createDynaBean(bean);
assertNotNull(dynaBean); assertNotNull(dynaBean);
assertEquals(bean, dynaBean.getBean()); assertEquals(bean, dynaBean.getBean());

View File

@ -102,7 +102,7 @@ public class SimpleCacheTest {
cache.get("key5", ()->"value5"); cache.get("key5", ()->"value5");
String key = null; String key = null;
for (Map.Entry<String, String> entry : cache) { for (final Map.Entry<String, String> entry : cache) {
if ("value3".equals(entry.getValue())) { if ("value3".equals(entry.getValue())) {
key = entry.getKey(); key = entry.getKey();
break; break;

View File

@ -996,25 +996,25 @@ public class CollUtilTest {
@Test @Test
public void zipTest2() { public void zipTest2() {
// 1. 正常情况测试 // 1. 正常情况测试
List<String> list1 = ListUtil.of("a", "b", "c"); final List<String> list1 = ListUtil.of("a", "b", "c");
List<Integer> list2 = ListUtil.of(1, 2, 3); final List<Integer> list2 = ListUtil.of(1, 2, 3);
List<String> result = CollUtil.zip(list1, list2, (s, i) -> s + i); final List<String> result = CollUtil.zip(list1, list2, (s, i) -> s + i);
assertEquals(ListUtil.of("a1", "b2", "c3"), result); assertEquals(ListUtil.of("a1", "b2", "c3"), result);
// 2. 空集合测试 // 2. 空集合测试
List<String> emptyList = ListUtil.of(); final List<String> emptyList = ListUtil.of();
List<String> emptyResult = CollUtil.zip(emptyList, list2, (s, i) -> s + i); final List<String> emptyResult = CollUtil.zip(emptyList, list2, (s, i) -> s + i);
assertTrue(emptyResult.isEmpty()); assertTrue(emptyResult.isEmpty());
// 3. 不同大小集合测试(以较小集合为准) // 3. 不同大小集合测试(以较小集合为准)
List<Integer> longerList = ListUtil.of(1, 2, 3, 4, 5); final List<Integer> longerList = ListUtil.of(1, 2, 3, 4, 5);
List<String> sizedResult = CollUtil.zip(list1, longerList, (s, i) -> s + i); final List<String> sizedResult = CollUtil.zip(list1, longerList, (s, i) -> s + i);
assertEquals(3, sizedResult.size()); assertEquals(3, sizedResult.size());
assertEquals("a1", sizedResult.get(0)); assertEquals("a1", sizedResult.get(0));
// 4. 自定义zipper函数测试 // 4. 自定义zipper函数测试
List<Double> list3 = ListUtil.of(1.1, 2.2, 3.3); final List<Double> list3 = ListUtil.of(1.1, 2.2, 3.3);
List<String> customResult = CollUtil.zip(list2, list3, (i, d) -> String.format("%d-%.1f", i, d)); final List<String> customResult = CollUtil.zip(list2, list3, (i, d) -> String.format("%d-%.1f", i, d));
assertEquals(ListUtil.of("1-1.1", "2-2.2", "3-3.3"), customResult); assertEquals(ListUtil.of("1-1.1", "2-2.2", "3-3.3"), customResult);
} }
@ -1166,11 +1166,11 @@ public class CollUtilTest {
@Test @Test
void getFirstTestWithPredicateTest(){ void getFirstTestWithPredicateTest(){
Animal dog = new Animal("dog", 2); final Animal dog = new Animal("dog", 2);
Animal cat = new Animal("cat", 3); final Animal cat = new Animal("cat", 3);
Animal bear = new Animal("bear", 4); final Animal bear = new Animal("bear", 4);
List<Animal> list = new ArrayList<>(); final List<Animal> list = new ArrayList<>();
list.add(dog); list.add(dog);
list.add(cat); list.add(cat);
list.add(bear); list.add(bear);

View File

@ -31,8 +31,8 @@ public class CopiedIterTest {
@Test @Test
public void copyOf() { public void copyOf() {
List<Integer> list = Arrays.asList(1, 2, 3); final List<Integer> list = Arrays.asList(1, 2, 3);
Iterator<Integer> iter = list.iterator(); final Iterator<Integer> iter = list.iterator();
Assertions.assertEquals((Integer)1, iter.next()); Assertions.assertEquals((Integer)1, iter.next());
Assertions.assertEquals((Integer)2, CopiedIter.copyOf(iter).next()); Assertions.assertEquals((Integer)2, CopiedIter.copyOf(iter).next());
@ -46,8 +46,8 @@ public class CopiedIterTest {
@Test @Test
public void next() { public void next() {
List<Integer> list = Arrays.asList(1, 2, 3); final List<Integer> list = Arrays.asList(1, 2, 3);
Iterator<Integer> iter = CopiedIter.copyOf(list.iterator()); final Iterator<Integer> iter = CopiedIter.copyOf(list.iterator());
Assertions.assertEquals((Integer)1, iter.next()); Assertions.assertEquals((Integer)1, iter.next());
Assertions.assertEquals((Integer)2, iter.next()); Assertions.assertEquals((Integer)2, iter.next());
Assertions.assertEquals((Integer)3, iter.next()); Assertions.assertEquals((Integer)3, iter.next());
@ -55,8 +55,8 @@ public class CopiedIterTest {
@Test @Test
public void remove() { public void remove() {
List<Integer> list = Arrays.asList(1, 2, 3); final List<Integer> list = Arrays.asList(1, 2, 3);
Iterator<Integer> iter = CopiedIter.copyOf(list.iterator()); final Iterator<Integer> iter = CopiedIter.copyOf(list.iterator());
Assertions.assertThrows(UnsupportedOperationException.class, iter::remove); Assertions.assertThrows(UnsupportedOperationException.class, iter::remove);
} }

View File

@ -30,16 +30,16 @@ public class EnumerationIterTest {
@Test @Test
public void testHasNext() { public void testHasNext() {
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator()); final Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration); final EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
Assertions.assertTrue(iter.hasNext()); Assertions.assertTrue(iter.hasNext());
Assertions.assertFalse(new EnumerationIter<>(new IteratorEnumeration<>(Collections.emptyIterator())).hasNext()); Assertions.assertFalse(new EnumerationIter<>(new IteratorEnumeration<>(Collections.emptyIterator())).hasNext());
} }
@Test @Test
public void testNext() { public void testNext() {
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator()); final Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration); final EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
Assertions.assertEquals((Integer)1, iter.next()); Assertions.assertEquals((Integer)1, iter.next());
Assertions.assertEquals((Integer)2, iter.next()); Assertions.assertEquals((Integer)2, iter.next());
Assertions.assertEquals((Integer)3, iter.next()); Assertions.assertEquals((Integer)3, iter.next());
@ -47,15 +47,15 @@ public class EnumerationIterTest {
@Test @Test
public void testRemove() { public void testRemove() {
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator()); final Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration); final EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
Assertions.assertThrows(UnsupportedOperationException.class, iter::remove); Assertions.assertThrows(UnsupportedOperationException.class, iter::remove);
} }
@Test @Test
public void testIterator() { public void testIterator() {
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator()); final Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration); final EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
Assertions.assertSame(iter, iter.iterator()); Assertions.assertSame(iter, iter.iterator());
} }

View File

@ -51,27 +51,27 @@ public class FilterIterTest {
@Test @Test
public void next() { public void next() {
// 只保留奇数 // 只保留奇数
Iterator<Integer> iter = new FilterIter<>(Arrays.asList(1, 2, 3).iterator(), i -> (i & 1) == 1); final Iterator<Integer> iter = new FilterIter<>(Arrays.asList(1, 2, 3).iterator(), i -> (i & 1) == 1);
Assertions.assertEquals((Integer)1, iter.next()); Assertions.assertEquals((Integer)1, iter.next());
Assertions.assertEquals((Integer)3, iter.next()); Assertions.assertEquals((Integer)3, iter.next());
} }
@Test @Test
public void remove() { public void remove() {
Iterator<Integer> iter = new FilterIter<>(Collections.emptyIterator(), i -> true); final Iterator<Integer> iter = new FilterIter<>(Collections.emptyIterator(), i -> true);
Assertions.assertThrows(IllegalStateException.class, iter::remove); Assertions.assertThrows(IllegalStateException.class, iter::remove);
} }
@Test @Test
public void getIterator() { public void getIterator() {
FilterIter<Integer> iter = new FilterIter<>(Collections.emptyIterator(), i -> true); final FilterIter<Integer> iter = new FilterIter<>(Collections.emptyIterator(), i -> true);
Assertions.assertSame(Collections.emptyIterator(), iter.getIterator()); Assertions.assertSame(Collections.emptyIterator(), iter.getIterator());
} }
@Test @Test
public void getFilter() { public void getFilter() {
Predicate<Integer> predicate = i -> true; final Predicate<Integer> predicate = i -> true;
FilterIter<Integer> iter = new FilterIter<>(Collections.emptyIterator(), predicate); final FilterIter<Integer> iter = new FilterIter<>(Collections.emptyIterator(), predicate);
Assertions.assertSame(predicate, iter.getFilter()); Assertions.assertSame(predicate, iter.getFilter());
} }

View File

@ -30,16 +30,16 @@ public class IteratorEnumerationTest {
@Test @Test
public void testHasMoreElements() { public void testHasMoreElements() {
List<Integer> list = Arrays.asList(1, 2, 3); final List<Integer> list = Arrays.asList(1, 2, 3);
IteratorEnumeration<Integer> enumeration = new IteratorEnumeration<>(list.iterator()); final IteratorEnumeration<Integer> enumeration = new IteratorEnumeration<>(list.iterator());
Assertions.assertTrue(enumeration.hasMoreElements()); Assertions.assertTrue(enumeration.hasMoreElements());
Assertions.assertFalse(new IteratorEnumeration<>(Collections.emptyIterator()).hasMoreElements()); Assertions.assertFalse(new IteratorEnumeration<>(Collections.emptyIterator()).hasMoreElements());
} }
@Test @Test
public void testNextElement() { public void testNextElement() {
List<Integer> list = Arrays.asList(1, 2, 3); final List<Integer> list = Arrays.asList(1, 2, 3);
IteratorEnumeration<Integer> enumeration = new IteratorEnumeration<>(list.iterator()); final IteratorEnumeration<Integer> enumeration = new IteratorEnumeration<>(list.iterator());
Assertions.assertEquals((Integer)1, enumeration.nextElement()); Assertions.assertEquals((Integer)1, enumeration.nextElement());
Assertions.assertEquals((Integer)2, enumeration.nextElement()); Assertions.assertEquals((Integer)2, enumeration.nextElement());
Assertions.assertEquals((Integer)3, enumeration.nextElement()); Assertions.assertEquals((Integer)3, enumeration.nextElement());

View File

@ -30,16 +30,16 @@ public class PartitionIterTest {
@Test @Test
public void testHasNext() { public void testHasNext() {
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator(); final Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator();
PartitionIter<Integer> partitionIter = new PartitionIter<>(iter, 2); final PartitionIter<Integer> partitionIter = new PartitionIter<>(iter, 2);
Assertions.assertTrue(partitionIter.hasNext()); Assertions.assertTrue(partitionIter.hasNext());
Assertions.assertFalse(new PartitionIter<>(Collections.emptyIterator(), 1).hasNext()); Assertions.assertFalse(new PartitionIter<>(Collections.emptyIterator(), 1).hasNext());
} }
@Test @Test
public void testNext() { public void testNext() {
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator(); final Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator();
PartitionIter<Integer> partitionIter = new PartitionIter<>(iter, 2); final PartitionIter<Integer> partitionIter = new PartitionIter<>(iter, 2);
Assertions.assertEquals(Arrays.asList(1, 2), partitionIter.next()); Assertions.assertEquals(Arrays.asList(1, 2), partitionIter.next());
Assertions.assertEquals(Arrays.asList(3, 4), partitionIter.next()); Assertions.assertEquals(Arrays.asList(3, 4), partitionIter.next());
} }

View File

@ -32,14 +32,14 @@ public class TransIterTest {
@Test @Test
public void testHasNext() { public void testHasNext() {
TransIter<Integer, String> iter = new TransIter<>(Arrays.asList(1, 2, 3).iterator(), String::valueOf); final TransIter<Integer, String> iter = new TransIter<>(Arrays.asList(1, 2, 3).iterator(), String::valueOf);
Assertions.assertTrue(iter.hasNext()); Assertions.assertTrue(iter.hasNext());
Assertions.assertFalse(new TransIter<>(Collections.emptyIterator(), Function.identity()).hasNext()); Assertions.assertFalse(new TransIter<>(Collections.emptyIterator(), Function.identity()).hasNext());
} }
@Test @Test
public void testNext() { public void testNext() {
TransIter<Integer, String> iter = new TransIter<>(Arrays.asList(1, 2, 3).iterator(), String::valueOf); final TransIter<Integer, String> iter = new TransIter<>(Arrays.asList(1, 2, 3).iterator(), String::valueOf);
Assertions.assertEquals("1", iter.next()); Assertions.assertEquals("1", iter.next());
Assertions.assertEquals("2", iter.next()); Assertions.assertEquals("2", iter.next());
Assertions.assertEquals("3", iter.next()); Assertions.assertEquals("3", iter.next());
@ -47,8 +47,8 @@ public class TransIterTest {
@Test @Test
public void testRemove() { public void testRemove() {
List<Integer> list = ListUtil.of(1, 2, 3); final List<Integer> list = ListUtil.of(1, 2, 3);
TransIter<Integer, String> iter = new TransIter<>(list.iterator(), String::valueOf); final TransIter<Integer, String> iter = new TransIter<>(list.iterator(), String::valueOf);
iter.next(); iter.next();
iter.remove(); iter.remove();
iter.next(); iter.next();

View File

@ -39,8 +39,8 @@ public class ShiChenTest {
assertEquals(1, ShiChen.toModernTime("子正").between(DateUnit.HOUR)); assertEquals(1, ShiChen.toModernTime("子正").between(DateUnit.HOUR));
// 测试所有时辰 // 测试所有时辰
String[] times = {"", "", "", "", "", "", "", "", "", "", "", ""}; final String[] times = {"", "", "", "", "", "", "", "", "", "", "", ""};
for (String time : times) { for (final String time : times) {
assertEquals(2, ShiChen.toModernTime(time + "").between(DateUnit.HOUR)); assertEquals(2, ShiChen.toModernTime(time + "").between(DateUnit.HOUR));
assertEquals(1, ShiChen.toModernTime(time + "").between(DateUnit.HOUR)); assertEquals(1, ShiChen.toModernTime(time + "").between(DateUnit.HOUR));
assertEquals(1, ShiChen.toModernTime(time + "").between(DateUnit.HOUR)); assertEquals(1, ShiChen.toModernTime(time + "").between(DateUnit.HOUR));

View File

@ -41,7 +41,7 @@ public class PredicateUtilTest {
@Test @Test
public void andTest() { public void andTest() {
boolean condition = Stream.of(1, 3, 5) final boolean condition = Stream.of(1, 3, 5)
.allMatch( .allMatch(
PredicateUtil.and( PredicateUtil.and(
Objects::nonNull, Objects::nonNull,
@ -54,7 +54,7 @@ public class PredicateUtilTest {
@Test @Test
public void orTest() { public void orTest() {
boolean condition = Stream.of(1, 3, 5) final boolean condition = Stream.of(1, 3, 5)
.anyMatch( .anyMatch(
PredicateUtil.or( PredicateUtil.or(
Objects::isNull, Objects::isNull,

View File

@ -50,7 +50,7 @@ public class MutableBoolTest extends BaseMutableTest<Boolean, MutableBool> {
* @return * @return
*/ */
@Override @Override
MutableBool getMutable(Boolean value) { MutableBool getMutable(final Boolean value) {
return new MutableBool(value); return new MutableBool(value);
} }
} }

View File

@ -48,7 +48,7 @@ public class MutableByteTest extends BaseMutableTest<Number, MutableByte> {
* @return * @return
*/ */
@Override @Override
MutableByte getMutable(Number value) { MutableByte getMutable(final Number value) {
return new MutableByte(value); return new MutableByte(value);
} }
} }

View File

@ -48,7 +48,7 @@ public class MutableDoubleTest extends BaseMutableTest<Number, MutableDouble> {
* @return * @return
*/ */
@Override @Override
MutableDouble getMutable(Number value) { MutableDouble getMutable(final Number value) {
return new MutableDouble(value); return new MutableDouble(value);
} }
} }

View File

@ -55,7 +55,7 @@ public class MutableEntryTest extends BaseMutableTest<Map.Entry<String, String>,
* @return * @return
*/ */
@Override @Override
MutableEntry<String, String> getMutable(Map.Entry<String, String> value) { MutableEntry<String, String> getMutable(final Map.Entry<String, String> value) {
return new MutableEntry<>(value.getKey(), value.getValue()); return new MutableEntry<>(value.getKey(), value.getValue());
} }
} }

View File

@ -47,7 +47,7 @@ public class MutableFloatTest extends BaseMutableTest<Number, MutableFloat> {
* @return * @return
*/ */
@Override @Override
MutableFloat getMutable(Number value) { MutableFloat getMutable(final Number value) {
return new MutableFloat(value); return new MutableFloat(value);
} }
} }

View File

@ -47,7 +47,7 @@ public class MutableIntTest extends BaseMutableTest<Number, MutableInt> {
* @return * @return
*/ */
@Override @Override
MutableInt getMutable(Number value) { MutableInt getMutable(final Number value) {
return new MutableInt(value); return new MutableInt(value);
} }
} }

View File

@ -47,7 +47,7 @@ public class MutableLongTest extends BaseMutableTest<Number, MutableLong> {
* @return * @return
*/ */
@Override @Override
MutableLong getMutable(Number value) { MutableLong getMutable(final Number value) {
return new MutableLong(value); return new MutableLong(value);
} }
} }

View File

@ -50,7 +50,7 @@ class MutableObjTest extends BaseMutableTest<String, MutableObj<String>> {
* @return * @return
*/ */
@Override @Override
MutableObj<String> getMutable(String value) { MutableObj<String> getMutable(final String value) {
return new MutableObj<>(value); return new MutableObj<>(value);
} }
} }

View File

@ -47,7 +47,7 @@ public class MutableShortTest extends BaseMutableTest<Number, MutableShort> {
* @return * @return
*/ */
@Override @Override
MutableShort getMutable(Number value) { MutableShort getMutable(final Number value) {
return new MutableShort(value); return new MutableShort(value);
} }
} }

View File

@ -51,7 +51,7 @@ public class MutableTripleTest extends BaseMutableTest<MutableTriple<String, Str
* @return * @return
*/ */
@Override @Override
MutableTriple<String, String, String> getMutable(MutableTriple<String, String, String> value) { MutableTriple<String, String, String> getMutable(final MutableTriple<String, String, String> value) {
return new MutableTriple<>(value.getLeft(), value.getMiddle(), value.getRight()); return new MutableTriple<>(value.getLeft(), value.getMiddle(), value.getRight());
} }
} }

View File

@ -30,9 +30,9 @@ public class BoundTest {
@Test @Test
@DisplayName("测试相邻区间合并") @DisplayName("测试相邻区间合并")
void testUnionIfIntersectedWithAdjacentRanges() { void testUnionIfIntersectedWithAdjacentRanges() {
BoundedRange<Integer> range1 = BoundedRange.close(1, 3); final BoundedRange<Integer> range1 = BoundedRange.close(1, 3);
BoundedRange<Integer> range2 = BoundedRange.close(3, 5); final BoundedRange<Integer> range2 = BoundedRange.close(3, 5);
BoundedRange<Integer> result = BoundedRangeOperation.unionIfIntersected(range1, range2); final BoundedRange<Integer> result = BoundedRangeOperation.unionIfIntersected(range1, range2);
assertEquals(Bound.atLeast(1), result.getLowerBound()); assertEquals(Bound.atLeast(1), result.getLowerBound());
assertEquals(Bound.atMost(5), result.getUpperBound()); assertEquals(Bound.atMost(5), result.getUpperBound());
@ -40,8 +40,8 @@ public class BoundTest {
@Test @Test
void isDisjointTest(){ void isDisjointTest(){
BoundedRange<Integer> range1 = BoundedRange.close(1, 3); final BoundedRange<Integer> range1 = BoundedRange.close(1, 3);
BoundedRange<Integer> range2 = BoundedRange.close(3, 5); final BoundedRange<Integer> range2 = BoundedRange.close(3, 5);
// 点重合相交 // 点重合相交
assertFalse(range1.isDisjoint(range2)); assertFalse(range1.isDisjoint(range2));
} }

View File

@ -43,9 +43,9 @@ public class RangeTest {
@Test @Test
@DisplayName("测试不包含起始元素的迭代") @DisplayName("测试不包含起始元素的迭代")
void testIteratorWithoutIncludeStart() { void testIteratorWithoutIncludeStart() {
Range<Integer> range = new Range<>(1, 5, (current, end, index) -> current + 1, false, true); final Range<Integer> range = new Range<>(1, 5, (current, end, index) -> current + 1, false, true);
List<Integer> elements = new ArrayList<>(); final List<Integer> elements = new ArrayList<>();
for (Integer i : range) { for (final Integer i : range) {
elements.add(i); elements.add(i);
} }

View File

@ -24,8 +24,8 @@ class PhantomObjTest {
@Test @Test
@DisplayName("测试 equals 方法与不同引用对象比较") @DisplayName("测试 equals 方法与不同引用对象比较")
void testEqualsWithDifferentReferent() { void testEqualsWithDifferentReferent() {
String differentObject = "different"; final String differentObject = "different";
PhantomObj<String> anotherPhantomObj = new PhantomObj<>(differentObject, queue); final PhantomObj<String> anotherPhantomObj = new PhantomObj<>(differentObject, queue);
assertFalse(phantomObj.equals(anotherPhantomObj)); assertFalse(phantomObj.equals(anotherPhantomObj));
} }
} }

View File

@ -28,7 +28,7 @@ public class IncrementSelectorTest {
*/ */
@Test @Test
void testSelectNormalCycle() { void testSelectNormalCycle() {
IncrementSelector<String> selector = new IncrementSelector<>(List.of("A", "B", "C")); final IncrementSelector<String> selector = new IncrementSelector<>(List.of("A", "B", "C"));
assertEquals("A", selector.select()); // 第一次调用应返回第一个元素 assertEquals("A", selector.select()); // 第一次调用应返回第一个元素
assertEquals("B", selector.select()); // 第二次调用应返回第二个元素 assertEquals("B", selector.select()); // 第二次调用应返回第二个元素

View File

@ -28,16 +28,16 @@ public class CollectionValueMapTest {
@Test @Test
public void putTest() { public void putTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
Assertions.assertNull(map.put(1, Arrays.asList("a", "b"))); Assertions.assertNull(map.put(1, Arrays.asList("a", "b")));
Collection<String> collection = map.put(1, Arrays.asList("c", "d")); final Collection<String> collection = map.put(1, Arrays.asList("c", "d"));
Assertions.assertEquals(Arrays.asList("a", "b"), collection); Assertions.assertEquals(Arrays.asList("a", "b"), collection);
} }
@Test @Test
public void putAllTest() { public void putAllTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
Map<Integer, Collection<String>> source = new HashMap<>(); final Map<Integer, Collection<String>> source = new HashMap<>();
source.put(1, Arrays.asList("a", "b", "c")); source.put(1, Arrays.asList("a", "b", "c"));
map.putAll(source); map.putAll(source);
Assertions.assertEquals(1, map.size()); Assertions.assertEquals(1, map.size());
@ -46,7 +46,7 @@ public class CollectionValueMapTest {
@Test @Test
public void putValueTest() { public void putValueTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
Assertions.assertTrue(map.putValue(1, "a")); Assertions.assertTrue(map.putValue(1, "a"));
Assertions.assertTrue(map.putValue(1, "b")); Assertions.assertTrue(map.putValue(1, "b"));
Assertions.assertTrue(map.putValue(1, "c")); Assertions.assertTrue(map.putValue(1, "c"));
@ -56,12 +56,12 @@ public class CollectionValueMapTest {
@Test @Test
public void putAllValueTest() { public void putAllValueTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
Assertions.assertTrue(map.putAllValues(1, Arrays.asList("a", "b", "c"))); Assertions.assertTrue(map.putAllValues(1, Arrays.asList("a", "b", "c")));
Assertions.assertEquals(1, map.size()); Assertions.assertEquals(1, map.size());
Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.get(1)); Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
Map<Integer, Collection<String>> source = new HashMap<>(); final Map<Integer, Collection<String>> source = new HashMap<>();
Assertions.assertTrue(map.putValue(1, "e")); Assertions.assertTrue(map.putValue(1, "e"));
Assertions.assertTrue(map.putValue(1, "f")); Assertions.assertTrue(map.putValue(1, "f"));
map.putAllValues(source); map.putAllValues(source);
@ -70,14 +70,14 @@ public class CollectionValueMapTest {
@Test @Test
public void putValuesTest() { public void putValuesTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
Assertions.assertTrue(map.putValues(1, "a", "b", "c")); Assertions.assertTrue(map.putValues(1, "a", "b", "c"));
Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.get(1)); Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
} }
@Test @Test
public void testFilterAllValues() { public void testFilterAllValues() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
Assertions.assertTrue(map.putValues(1, "a", "b", "c")); Assertions.assertTrue(map.putValues(1, "a", "b", "c"));
Assertions.assertTrue(map.putValues(2, "a", "b", "c")); Assertions.assertTrue(map.putValues(2, "a", "b", "c"));
@ -92,7 +92,7 @@ public class CollectionValueMapTest {
@Test @Test
public void testReplaceAllValues() { public void testReplaceAllValues() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
Assertions.assertTrue(map.putValues(1, "a", "b", "c")); Assertions.assertTrue(map.putValues(1, "a", "b", "c"));
Assertions.assertTrue(map.putValues(2, "a", "b", "c")); Assertions.assertTrue(map.putValues(2, "a", "b", "c"));
@ -107,7 +107,7 @@ public class CollectionValueMapTest {
@Test @Test
public void removeValueTest() { public void removeValueTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertFalse(map.removeValue(1, "d")); Assertions.assertFalse(map.removeValue(1, "d"));
Assertions.assertTrue(map.removeValue(1, "c")); Assertions.assertTrue(map.removeValue(1, "c"));
@ -116,7 +116,7 @@ public class CollectionValueMapTest {
@Test @Test
public void removeAllValuesTest() { public void removeAllValuesTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f"))); Assertions.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f")));
Assertions.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c"))); Assertions.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c")));
@ -125,7 +125,7 @@ public class CollectionValueMapTest {
@Test @Test
public void removeValuesTest() { public void removeValuesTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertFalse(map.removeValues(1, "e", "f")); Assertions.assertFalse(map.removeValues(1, "e", "f"));
Assertions.assertTrue(map.removeValues(1, "b", "c")); Assertions.assertTrue(map.removeValues(1, "b", "c"));
@ -134,7 +134,7 @@ public class CollectionValueMapTest {
@Test @Test
public void getValuesTest() { public void getValuesTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertEquals(Collections.emptyList(), map.getValues(2)); Assertions.assertEquals(Collections.emptyList(), map.getValues(2));
Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.getValues(1)); Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.getValues(1));
@ -142,7 +142,7 @@ public class CollectionValueMapTest {
@Test @Test
public void sizeTest() { public void sizeTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertEquals(0, map.size(2)); Assertions.assertEquals(0, map.size(2));
Assertions.assertEquals(3, map.size(1)); Assertions.assertEquals(3, map.size(1));
@ -150,10 +150,10 @@ public class CollectionValueMapTest {
@Test @Test
public void allForEachTest() { public void allForEachTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(); final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
List<Integer> keys = new ArrayList<>(); final List<Integer> keys = new ArrayList<>();
List<String> values = new ArrayList<>(); final List<String> values = new ArrayList<>();
map.allForEach((k, v) -> { map.allForEach((k, v) -> {
keys.add(k); keys.add(k);
values.add(v); values.add(v);
@ -164,7 +164,7 @@ public class CollectionValueMapTest {
@Test @Test
public void allValuesTest() { public void allValuesTest() {
MultiValueMap<Integer, String> map = new CollectionValueMap<>(new LinkedHashMap<>()); final MultiValueMap<Integer, String> map = new CollectionValueMap<>(new LinkedHashMap<>());
map.putAllValues(1, Arrays.asList("a", "b", "c")); map.putAllValues(1, Arrays.asList("a", "b", "c"));
map.putAllValues(2, Arrays.asList("d", "e")); map.putAllValues(2, Arrays.asList("d", "e"));
Assertions.assertEquals( Assertions.assertEquals(

View File

@ -28,16 +28,16 @@ public class ListValueMapTest {
@Test @Test
public void putTest() { public void putTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
Assertions.assertNull(map.put(1, Arrays.asList("a", "b"))); Assertions.assertNull(map.put(1, Arrays.asList("a", "b")));
Collection<String> collection = map.put(1, Arrays.asList("c", "d")); final Collection<String> collection = map.put(1, Arrays.asList("c", "d"));
Assertions.assertEquals(Arrays.asList("a", "b"), collection); Assertions.assertEquals(Arrays.asList("a", "b"), collection);
} }
@Test @Test
public void putAllTest() { public void putAllTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
Map<Integer, Collection<String>> source = new HashMap<>(); final Map<Integer, Collection<String>> source = new HashMap<>();
source.put(1, Arrays.asList("a", "b", "c")); source.put(1, Arrays.asList("a", "b", "c"));
map.putAll(source); map.putAll(source);
Assertions.assertEquals(1, map.size()); Assertions.assertEquals(1, map.size());
@ -46,7 +46,7 @@ public class ListValueMapTest {
@Test @Test
public void putValueTest() { public void putValueTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
Assertions.assertTrue(map.putValue(1, "a")); Assertions.assertTrue(map.putValue(1, "a"));
Assertions.assertTrue(map.putValue(1, "b")); Assertions.assertTrue(map.putValue(1, "b"));
Assertions.assertTrue(map.putValue(1, "c")); Assertions.assertTrue(map.putValue(1, "c"));
@ -56,12 +56,12 @@ public class ListValueMapTest {
@Test @Test
public void putAllValueTest() { public void putAllValueTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
Assertions.assertTrue(map.putAllValues(1, Arrays.asList("a", "b", "c"))); Assertions.assertTrue(map.putAllValues(1, Arrays.asList("a", "b", "c")));
Assertions.assertEquals(1, map.size()); Assertions.assertEquals(1, map.size());
Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.get(1)); Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
Map<Integer, Collection<String>> source = new HashMap<>(); final Map<Integer, Collection<String>> source = new HashMap<>();
Assertions.assertTrue(map.putValue(1, "e")); Assertions.assertTrue(map.putValue(1, "e"));
Assertions.assertTrue(map.putValue(1, "f")); Assertions.assertTrue(map.putValue(1, "f"));
map.putAllValues(source); map.putAllValues(source);
@ -70,14 +70,14 @@ public class ListValueMapTest {
@Test @Test
public void putValuesTest() { public void putValuesTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
Assertions.assertTrue(map.putValues(1, "a", "b", "c")); Assertions.assertTrue(map.putValues(1, "a", "b", "c"));
Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.get(1)); Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
} }
@Test @Test
public void removeValueTest() { public void removeValueTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertFalse(map.removeValue(1, "d")); Assertions.assertFalse(map.removeValue(1, "d"));
Assertions.assertTrue(map.removeValue(1, "c")); Assertions.assertTrue(map.removeValue(1, "c"));
@ -86,7 +86,7 @@ public class ListValueMapTest {
@Test @Test
public void removeAllValuesTest() { public void removeAllValuesTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f"))); Assertions.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f")));
Assertions.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c"))); Assertions.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c")));
@ -95,7 +95,7 @@ public class ListValueMapTest {
@Test @Test
public void removeValuesTest() { public void removeValuesTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertFalse(map.removeValues(1, "e", "f")); Assertions.assertFalse(map.removeValues(1, "e", "f"));
Assertions.assertTrue(map.removeValues(1, "b", "c")); Assertions.assertTrue(map.removeValues(1, "b", "c"));
@ -104,7 +104,7 @@ public class ListValueMapTest {
@Test @Test
public void testFilterAllValues() { public void testFilterAllValues() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
Assertions.assertTrue(map.putValues(1, "a", "b", "c")); Assertions.assertTrue(map.putValues(1, "a", "b", "c"));
Assertions.assertTrue(map.putValues(2, "a", "b", "c")); Assertions.assertTrue(map.putValues(2, "a", "b", "c"));
@ -119,7 +119,7 @@ public class ListValueMapTest {
@Test @Test
public void testReplaceAllValues() { public void testReplaceAllValues() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
Assertions.assertTrue(map.putValues(1, "a", "b", "c")); Assertions.assertTrue(map.putValues(1, "a", "b", "c"));
Assertions.assertTrue(map.putValues(2, "a", "b", "c")); Assertions.assertTrue(map.putValues(2, "a", "b", "c"));
@ -134,7 +134,7 @@ public class ListValueMapTest {
@Test @Test
public void getValuesTest() { public void getValuesTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertEquals(Collections.emptyList(), map.getValues(2)); Assertions.assertEquals(Collections.emptyList(), map.getValues(2));
Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.getValues(1)); Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.getValues(1));
@ -142,7 +142,7 @@ public class ListValueMapTest {
@Test @Test
public void sizeTest() { public void sizeTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertEquals(0, map.size(2)); Assertions.assertEquals(0, map.size(2));
Assertions.assertEquals(3, map.size(1)); Assertions.assertEquals(3, map.size(1));
@ -150,10 +150,10 @@ public class ListValueMapTest {
@Test @Test
public void allForEachTest() { public void allForEachTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
List<Integer> keys = new ArrayList<>(); final List<Integer> keys = new ArrayList<>();
List<String> values = new ArrayList<>(); final List<String> values = new ArrayList<>();
map.allForEach((k, v) -> { map.allForEach((k, v) -> {
keys.add(k); keys.add(k);
values.add(v); values.add(v);
@ -164,7 +164,7 @@ public class ListValueMapTest {
@Test @Test
public void allValuesTest() { public void allValuesTest() {
MultiValueMap<Integer, String> map = new ListValueMap<>(); final MultiValueMap<Integer, String> map = new ListValueMap<>();
map.putAllValues(1, Arrays.asList("a", "b", "c")); map.putAllValues(1, Arrays.asList("a", "b", "c"));
map.putAllValues(2, Arrays.asList("d", "e")); map.putAllValues(2, Arrays.asList("d", "e"));
Assertions.assertEquals( Assertions.assertEquals(

View File

@ -28,16 +28,16 @@ public class SetValueMapTest {
@Test @Test
public void putTest() { public void putTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
Assertions.assertNull(map.put(1, Arrays.asList("a", "b"))); Assertions.assertNull(map.put(1, Arrays.asList("a", "b")));
Collection<String> collection = map.put(1, Arrays.asList("c", "d")); final Collection<String> collection = map.put(1, Arrays.asList("c", "d"));
Assertions.assertEquals(Arrays.asList("a", "b"), collection); Assertions.assertEquals(Arrays.asList("a", "b"), collection);
} }
@Test @Test
public void putAllTest() { public void putAllTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
Map<Integer, Collection<String>> source = new HashMap<>(); final Map<Integer, Collection<String>> source = new HashMap<>();
source.put(1, Arrays.asList("a", "b", "c")); source.put(1, Arrays.asList("a", "b", "c"));
map.putAll(source); map.putAll(source);
Assertions.assertEquals(1, map.size()); Assertions.assertEquals(1, map.size());
@ -46,7 +46,7 @@ public class SetValueMapTest {
@Test @Test
public void putValueTest() { public void putValueTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
Assertions.assertTrue(map.putValue(1, "a")); Assertions.assertTrue(map.putValue(1, "a"));
Assertions.assertTrue(map.putValue(1, "b")); Assertions.assertTrue(map.putValue(1, "b"));
Assertions.assertTrue(map.putValue(1, "c")); Assertions.assertTrue(map.putValue(1, "c"));
@ -56,12 +56,12 @@ public class SetValueMapTest {
@Test @Test
public void putAllValueTest() { public void putAllValueTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
Assertions.assertTrue(map.putAllValues(1, Arrays.asList("a", "b", "c"))); Assertions.assertTrue(map.putAllValues(1, Arrays.asList("a", "b", "c")));
Assertions.assertEquals(1, map.size()); Assertions.assertEquals(1, map.size());
Assertions.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.get(1)); Assertions.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.get(1));
Map<Integer, Collection<String>> source = new HashMap<>(); final Map<Integer, Collection<String>> source = new HashMap<>();
Assertions.assertTrue(map.putValue(1, "e")); Assertions.assertTrue(map.putValue(1, "e"));
Assertions.assertFalse(map.putValue(1, "e")); Assertions.assertFalse(map.putValue(1, "e"));
Assertions.assertTrue(map.putValue(1, "f")); Assertions.assertTrue(map.putValue(1, "f"));
@ -72,14 +72,14 @@ public class SetValueMapTest {
@Test @Test
public void putValuesTest() { public void putValuesTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
Assertions.assertTrue(map.putValues(1, "a", "b", "c")); Assertions.assertTrue(map.putValues(1, "a", "b", "c"));
Assertions.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.get(1)); Assertions.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.get(1));
} }
@Test @Test
public void removeValueTest() { public void removeValueTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertFalse(map.removeValue(1, "d")); Assertions.assertFalse(map.removeValue(1, "d"));
Assertions.assertTrue(map.removeValue(1, "c")); Assertions.assertTrue(map.removeValue(1, "c"));
@ -88,7 +88,7 @@ public class SetValueMapTest {
@Test @Test
public void removeAllValuesTest() { public void removeAllValuesTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f"))); Assertions.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f")));
Assertions.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c"))); Assertions.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c")));
@ -97,7 +97,7 @@ public class SetValueMapTest {
@Test @Test
public void removeValuesTest() { public void removeValuesTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertFalse(map.removeValues(1, "e", "f")); Assertions.assertFalse(map.removeValues(1, "e", "f"));
Assertions.assertTrue(map.removeValues(1, "b", "c")); Assertions.assertTrue(map.removeValues(1, "b", "c"));
@ -106,7 +106,7 @@ public class SetValueMapTest {
@Test @Test
public void testFilterAllValues() { public void testFilterAllValues() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
Assertions.assertTrue(map.putValues(1, "a", "b", "c")); Assertions.assertTrue(map.putValues(1, "a", "b", "c"));
Assertions.assertTrue(map.putValues(2, "a", "b", "c")); Assertions.assertTrue(map.putValues(2, "a", "b", "c"));
@ -121,7 +121,7 @@ public class SetValueMapTest {
@Test @Test
public void testReplaceAllValues() { public void testReplaceAllValues() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
Assertions.assertTrue(map.putValues(1, "a", "b", "c")); Assertions.assertTrue(map.putValues(1, "a", "b", "c"));
Assertions.assertTrue(map.putValues(2, "a", "b", "c")); Assertions.assertTrue(map.putValues(2, "a", "b", "c"));
@ -136,7 +136,7 @@ public class SetValueMapTest {
@Test @Test
public void getValuesTest() { public void getValuesTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertEquals(Collections.emptyList(), map.getValues(2)); Assertions.assertEquals(Collections.emptyList(), map.getValues(2));
Assertions.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.getValues(1)); Assertions.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.getValues(1));
@ -144,7 +144,7 @@ public class SetValueMapTest {
@Test @Test
public void sizeTest() { public void sizeTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
Assertions.assertEquals(0, map.size(2)); Assertions.assertEquals(0, map.size(2));
Assertions.assertEquals(3, map.size(1)); Assertions.assertEquals(3, map.size(1));
@ -152,10 +152,10 @@ public class SetValueMapTest {
@Test @Test
public void allForEachTest() { public void allForEachTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
map.putValues(1, "a", "b", "c"); map.putValues(1, "a", "b", "c");
List<Integer> keys = new ArrayList<>(); final List<Integer> keys = new ArrayList<>();
List<String> values = new ArrayList<>(); final List<String> values = new ArrayList<>();
map.allForEach((k, v) -> { map.allForEach((k, v) -> {
keys.add(k); keys.add(k);
values.add(v); values.add(v);
@ -166,7 +166,7 @@ public class SetValueMapTest {
@Test @Test
public void allValuesTest() { public void allValuesTest() {
MultiValueMap<Integer, String> map = new SetValueMap<>(); final MultiValueMap<Integer, String> map = new SetValueMap<>();
map.putAllValues(1, Arrays.asList("a", "b", "c")); map.putAllValues(1, Arrays.asList("a", "b", "c"));
map.putAllValues(2, Arrays.asList("d", "e")); map.putAllValues(2, Arrays.asList("d", "e"));
Assertions.assertEquals( Assertions.assertEquals(

View File

@ -27,7 +27,7 @@ public class TolerantMapTest {
@Test @Test
public void testSerialize() { public void testSerialize() {
TolerantMap<String, String> map = TolerantMap.of(new HashMap<>(), "default"); final TolerantMap<String, String> map = TolerantMap.of(new HashMap<>(), "default");
map.put("monday", "星期一"); map.put("monday", "星期一");
map.put("tuesday", "星期二"); map.put("tuesday", "星期二");
@ -39,7 +39,7 @@ public class TolerantMapTest {
@Test @Test
public void testClone() { public void testClone() {
TolerantMap<String, String> map = TolerantMap.of(new HashMap<>(), "default"); final TolerantMap<String, String> map = TolerantMap.of(new HashMap<>(), "default");
map.put("monday", "星期一"); map.put("monday", "星期一");
map.put("tuesday", "星期二"); map.put("tuesday", "星期二");
@ -50,7 +50,7 @@ public class TolerantMapTest {
@Test @Test
public void testGet() { public void testGet() {
TolerantMap<String, String> map = TolerantMap.of(new HashMap<>(), "default"); final TolerantMap<String, String> map = TolerantMap.of(new HashMap<>(), "default");
map.put("monday", "星期一"); map.put("monday", "星期一");
map.put("tuesday", "星期二"); map.put("tuesday", "星期二");

View File

@ -43,7 +43,7 @@ public class MoneyTest {
@Test @Test
public void currencyScalingTest() { public void currencyScalingTest() {
Money jpyMoney = new Money(0, Currency.getInstance("JPY")); final Money jpyMoney = new Money(0, Currency.getInstance("JPY"));
jpyMoney.setAmount(BigDecimal.ONE); jpyMoney.setAmount(BigDecimal.ONE);
assertEquals(1, jpyMoney.getCent()); assertEquals(1, jpyMoney.getCent());
} }

View File

@ -49,8 +49,8 @@ public class FieldUtilTest {
// 如果子类与父类中存在同名字段则这两个字段同时存在子类字段在前父类字段在后 // 如果子类与父类中存在同名字段则这两个字段同时存在子类字段在前父类字段在后
fields = FieldUtil.getFields(TestSubUser.class); fields = FieldUtil.getFields(TestSubUser.class);
assertEquals(4, fields.length); assertEquals(4, fields.length);
List<Field> idFieldList = Arrays.stream(fields).filter(f -> Objects.equals(f.getName(), TestSubUser.Fields.id)).collect(Collectors.toList()); final List<Field> idFieldList = Arrays.stream(fields).filter(f -> Objects.equals(f.getName(), TestSubUser.Fields.id)).collect(Collectors.toList());
Field firstIdField = CollUtil.getFirst(idFieldList); final Field firstIdField = CollUtil.getFirst(idFieldList);
assertEquals(Objects.requireNonNull(firstIdField).getDeclaringClass().getName(), TestSubUser.class.getName()); assertEquals(Objects.requireNonNull(firstIdField).getDeclaringClass().getName(), TestSubUser.class.getName());
} }
@ -101,7 +101,7 @@ public class FieldUtilTest {
public void getFieldMapTest() { public void getFieldMapTest() {
// 获取指定类中字段名和字段对应的有序Map包括其父类中的字段 // 获取指定类中字段名和字段对应的有序Map包括其父类中的字段
// 如果子类与父类中存在同名字段则后者覆盖前者 // 如果子类与父类中存在同名字段则后者覆盖前者
Map<String, Field> fieldMap = FieldUtil.getFieldMap(TestSubUser.class); final Map<String, Field> fieldMap = FieldUtil.getFieldMap(TestSubUser.class);
assertEquals(3, fieldMap.size()); assertEquals(3, fieldMap.size());
} }

View File

@ -44,7 +44,7 @@ public class EasyStreamTest {
@Test @Test
void testIterateHierarchies() { void testIterateHierarchies() {
// 创建一个三层的树结构每个节点都有两个子节点 // 创建一个三层的树结构每个节点都有两个子节点
Node node = new Node("1", Arrays.asList( final Node node = new Node("1", Arrays.asList(
new Node("1-1", Arrays.asList( new Node("1-1", Arrays.asList(
new Node("1-1-1", null), new Node("1-1-1", null),
new Node("1-1-2", null) new Node("1-1-2", null)
@ -56,13 +56,13 @@ public class EasyStreamTest {
)); ));
// 按广度度优先遍历树结构 // 按广度度优先遍历树结构
List<String> allNodes = new ArrayList<>(); final List<String> allNodes = new ArrayList<>();
EasyStream.iterateHierarchies(node, node1 -> node1.children) EasyStream.iterateHierarchies(node, node1 -> node1.children)
.forEach(node1 -> allNodes.add(node1.id)); .forEach(node1 -> allNodes.add(node1.id));
Assertions.assertEquals(Arrays.asList("1", "1-1", "1-2", "1-1-1", "1-1-2", "1-2-1", "1-2-2"), allNodes); Assertions.assertEquals(Arrays.asList("1", "1-1", "1-2", "1-1-1", "1-1-2", "1-2-1", "1-2-2"), allNodes);
// 按广度度优先遍历树结构忽略id为1-1的节点与以其为根节点的子树 // 按广度度优先遍历树结构忽略id为1-1的节点与以其为根节点的子树
List<String> filteredNodes = new ArrayList<>(); final List<String> filteredNodes = new ArrayList<>();
EasyStream.iterateHierarchies(node, node1 -> node1.children, node1 -> !node1.id.equals("1-1")) EasyStream.iterateHierarchies(node, node1 -> node1.children, node1 -> !node1.id.equals("1-1"))
.forEach(node1 -> filteredNodes.add(node1.id)); .forEach(node1 -> filteredNodes.add(node1.id));
Assertions.assertEquals(Arrays.asList("1", "1-2", "1-2-1", "1-2-2"), filteredNodes); Assertions.assertEquals(Arrays.asList("1", "1-2", "1-2-1", "1-2-2"), filteredNodes);
@ -610,11 +610,11 @@ public class EasyStreamTest {
private static class Node { private static class Node {
private final String id; private final String id;
private List<Node> children; private List<Node> children;
private Node(String id, List<Node> children) { private Node(final String id, final List<Node> children) {
this.id = id; this.id = id;
this.children = children; this.children = children;
} }
public Node(String id) { public Node(final String id) {
this.id = id; this.id = id;
} }
} }

View File

@ -0,0 +1,146 @@
package cn.hutool.v7.core.text.finder;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/**
* @author Lettuceleaves
*/
public class StrFinderTest {
@Test
public void testForward() {
// 正向查找
final String text = "Hello Hutool World";
final StrFinder finder = StrFinder.of("Hutool", false);
finder.setText(text);
Assertions.assertEquals(6, finder.start(0));
Assertions.assertEquals(-1, finder.start(7));
}
@Test
public void testForwardIgnoreCase() {
// 正向查找忽略大小写
final String text = "Hello HUTOOL World";
final StrFinder finder = StrFinder.of("hutool", true);
finder.setText(text);
Assertions.assertEquals(6, finder.start(0));
}
@Test
public void testReverseBasic() {
// 反向查找
final String text = "abc abc abc";
final StrFinder finder = StrFinder.of("abc", false);
finder.setNegative(true);
finder.setText(text);
Assertions.assertEquals(8, finder.start(text.length() - 1));
Assertions.assertEquals(4, finder.start(7));
Assertions.assertEquals(0, finder.start(2));
}
@Test
public void testReverseIgnoreCase() {
// 反向查找忽略大小写
final String text = "ABC abc Abc";
final StrFinder finder = StrFinder.of("abc", true);
finder.setNegative(true);
finder.setText(text);
Assertions.assertEquals(8, finder.start(text.length() - 1));
}
@Test
public void testAlgorithmEdgeCase() {
final String text = "ababa";
final StrFinder forward = StrFinder.of("aba", false);
forward.setText(text);
Assertions.assertEquals(0, forward.start(0));
Assertions.assertEquals(2, forward.start(1));
final StrFinder reverse = StrFinder.of("aba", false);
reverse.setNegative(true);
reverse.setText(text);
Assertions.assertEquals(2, reverse.start(4));
Assertions.assertEquals(0, reverse.start(1));
}
@Test
public void testZeroCopy() {
// 验证toString()优化
final StringBuilder bigText = new StringBuilder();
bigText.append("ignore-".repeat(1000));
bigText.append("TARGET");
bigText.append("-ignore");
final StrFinder finder = StrFinder.of("TARGET", false);
finder.setText(bigText);
Assertions.assertEquals(7000, finder.start(0));
}
@Test
public void testChinese() {
// 中文测试
final String text = "希望pr能够通过";
final StrFinder finder = StrFinder.of("通过", false);
finder.setText(text);
Assertions.assertEquals(6, finder.start(0));
}
@Test
public void testNotFound() {
// 不包含字符串
final StrFinder finder = StrFinder.of("NotExists", false);
finder.setText("Hello World");
Assertions.assertEquals(-1, finder.start(0));
}
@Test
public void benchmark() {
System.out.println("正在生成测试数据...");
final StringBuilder sb = new StringBuilder();
final String base = "abcdefghijklmnopqrstuvwxyz0123456789-";
sb.append(base.repeat(500));
final String target = "HUTOOL_TARGET";
sb.append(target);
final String textStr = sb.toString();
final int loop = 100;
for (int i = 0; i < 100; i++) {
StrFinder.of(target, false).setText(textStr).start(0);
}
long start = System.currentTimeMillis();
for (int i = 0; i < loop; i++) {
final int index = textStr.indexOf(target);
if (index == -1) throw new RuntimeException("Bug!");
}
long end = System.currentTimeMillis();
System.out.println("1. JDK String.indexOf耗时: " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < loop; i++) {
final int index = StrFinder.of(target, false).setText(textStr).start(0);
if (index == -1) throw new RuntimeException("Bug!");
}
end = System.currentTimeMillis();
System.out.println("2. StrFinder (String) 耗时: " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < loop; i++) {
final int index = StrFinder.of(target, false).setText(sb).start(0);
if (index == -1) throw new RuntimeException("Bug!");
}
end = System.currentTimeMillis();
System.out.println("3. StrFinder (Builder)耗时: " + (end - start) + "ms");
}
}

View File

@ -33,25 +33,25 @@ class HierarchyIteratorTest {
@Test @Test
void testNoSuchElementException() { void testNoSuchElementException() {
Node node = createTree(); final Node node = createTree();
// 根节点也被忽略将会抛出异常 // 根节点也被忽略将会抛出异常
Assertions.assertThrows(IllegalArgumentException.class, () -> HierarchyIterator.depthFirst(node, node1 -> node1.children, node1 -> false)); Assertions.assertThrows(IllegalArgumentException.class, () -> HierarchyIterator.depthFirst(node, node1 -> node1.children, node1 -> false));
// 忽略所有节点将会抛出NoSuchElementException // 忽略所有节点将会抛出NoSuchElementException
HierarchyIterator<Node> iterator = HierarchyIterator.depthFirst(node, node1 -> node1.children, node1 -> node1.id.equals("1")); final HierarchyIterator<Node> iterator = HierarchyIterator.depthFirst(node, node1 -> node1.children, node1 -> node1.id.equals("1"));
Assertions.assertSame(node, iterator.next()); Assertions.assertSame(node, iterator.next());
Assertions.assertThrows(NoSuchElementException.class, iterator::next); Assertions.assertThrows(NoSuchElementException.class, iterator::next);
} }
@Test @Test
void testDepthFirstWithFilter() { void testDepthFirstWithFilter() {
Node node = createTree(); final Node node = createTree();
// 按深度度优先遍历树结构忽略id为1-1的节点与以其为根节点的子树 // 按深度度优先遍历树结构忽略id为1-1的节点与以其为根节点的子树
List<String> nodes = new ArrayList<>(); final List<String> nodes = new ArrayList<>();
HierarchyIterator<Node> iterator = HierarchyIterator.depthFirst( final HierarchyIterator<Node> iterator = HierarchyIterator.depthFirst(
node, node1 -> node1.children, node1 -> !node1.id.equals("1-1") node, node1 -> node1.children, node1 -> !node1.id.equals("1-1")
); );
while (iterator.hasNext()) { while (iterator.hasNext()) {
Node node1 = iterator.next(); final Node node1 = iterator.next();
nodes.add(node1.id); nodes.add(node1.id);
} }
Assertions.assertEquals(Arrays.asList("1", "1-2", "1-2-1", "1-2-2"), nodes); Assertions.assertEquals(Arrays.asList("1", "1-2", "1-2-1", "1-2-2"), nodes);
@ -59,12 +59,12 @@ class HierarchyIteratorTest {
@Test @Test
void testDepthFirst() { void testDepthFirst() {
Node node = createTree(); final Node node = createTree();
// 按深度度优先遍历树结构 // 按深度度优先遍历树结构
List<String> nodes = new ArrayList<>(); final List<String> nodes = new ArrayList<>();
HierarchyIterator<Node> iterator = HierarchyIterator.depthFirst(node, node1 -> node1.children); final HierarchyIterator<Node> iterator = HierarchyIterator.depthFirst(node, node1 -> node1.children);
while (iterator.hasNext()) { while (iterator.hasNext()) {
Node node1 = iterator.next(); final Node node1 = iterator.next();
nodes.add(node1.id); nodes.add(node1.id);
} }
Assertions.assertEquals(Arrays.asList("1", "1-1", "1-1-1", "1-1-2", "1-2", "1-2-1", "1-2-2"), nodes); Assertions.assertEquals(Arrays.asList("1", "1-1", "1-1-1", "1-1-2", "1-2", "1-2-1", "1-2-2"), nodes);
@ -72,14 +72,14 @@ class HierarchyIteratorTest {
@Test @Test
void testBreadthFirstWithFilter() { void testBreadthFirstWithFilter() {
Node node = createTree(); final Node node = createTree();
// 按深度度优先遍历树结构忽略id为1-1的节点与以其为根节点的子树 // 按深度度优先遍历树结构忽略id为1-1的节点与以其为根节点的子树
List<String> nodes = new ArrayList<>(); final List<String> nodes = new ArrayList<>();
HierarchyIterator<Node> iterator = HierarchyIterator.breadthFirst( final HierarchyIterator<Node> iterator = HierarchyIterator.breadthFirst(
node, node1 -> node1.children, node1 -> !node1.id.equals("1-1") node, node1 -> node1.children, node1 -> !node1.id.equals("1-1")
); );
while (iterator.hasNext()) { while (iterator.hasNext()) {
Node node1 = iterator.next(); final Node node1 = iterator.next();
nodes.add(node1.id); nodes.add(node1.id);
} }
Assertions.assertEquals(Arrays.asList("1", "1-2", "1-2-1", "1-2-2"), nodes); Assertions.assertEquals(Arrays.asList("1", "1-2", "1-2-1", "1-2-2"), nodes);
@ -87,12 +87,12 @@ class HierarchyIteratorTest {
@Test @Test
void testBreadthFirst() { void testBreadthFirst() {
Node root = createGraph(); final Node root = createGraph();
// 按深度度优先遍历图结构 // 按深度度优先遍历图结构
List<String> nodes = new ArrayList<>(); final List<String> nodes = new ArrayList<>();
HierarchyIterator<Node> iterator = HierarchyIterator.breadthFirst(root, node -> node.children); final HierarchyIterator<Node> iterator = HierarchyIterator.breadthFirst(root, node -> node.children);
while (iterator.hasNext()) { while (iterator.hasNext()) {
Node node = iterator.next(); final Node node = iterator.next();
nodes.add(node.id); nodes.add(node.id);
} }
Assertions.assertEquals(Arrays.asList("1", "4", "2", "3"), nodes); Assertions.assertEquals(Arrays.asList("1", "4", "2", "3"), nodes);
@ -100,10 +100,10 @@ class HierarchyIteratorTest {
private static Node createGraph() { private static Node createGraph() {
// 构建一个包含四个节点的图每一个节点都有两个相邻节点 // 构建一个包含四个节点的图每一个节点都有两个相邻节点
Node node1 = new Node("1"); final Node node1 = new Node("1");
Node node2 = new Node("2"); final Node node2 = new Node("2");
Node node3 = new Node("3"); final Node node3 = new Node("3");
Node node4 = new Node("4"); final Node node4 = new Node("4");
node1.children = Arrays.asList(node4, node2); node1.children = Arrays.asList(node4, node2);
node2.children = Arrays.asList(node1, node3); node2.children = Arrays.asList(node1, node3);
node3.children = Arrays.asList(node2, node4); node3.children = Arrays.asList(node2, node4);
@ -131,11 +131,11 @@ class HierarchyIteratorTest {
private static class Node { private static class Node {
private final String id; private final String id;
private List<Node> children; private List<Node> children;
private Node(String id, List<Node> children) { private Node(final String id, final List<Node> children) {
this.id = id; this.id = id;
this.children = children; this.children = children;
} }
public Node(String id) { public Node(final String id) {
this.id = id; this.id = id;
} }
} }

View File

@ -238,13 +238,13 @@ public class ObjUtilTest {
@Test @Test
public void testLengthConsumesIterator() { public void testLengthConsumesIterator() {
List<String> list = Arrays.asList("a", "b", "c"); final List<String> list = Arrays.asList("a", "b", "c");
Iterator<String> iterator = list.iterator(); final Iterator<String> iterator = list.iterator();
// 迭代器第一次调用length // 迭代器第一次调用length
int length1 = ObjUtil.length(iterator); final int length1 = ObjUtil.length(iterator);
assertEquals(3, length1); assertEquals(3, length1);
// 迭代器第二次调用length - 迭代器已经被消耗返回0 // 迭代器第二次调用length - 迭代器已经被消耗返回0
int length2 = ObjUtil.length(iterator); final int length2 = ObjUtil.length(iterator);
assertEquals(0, length2); // 但当前实现会重新遍历但iterator已经没有元素了 assertEquals(0, length2); // 但当前实现会重新遍历但iterator已经没有元素了
// 尝试使用迭代器 - 已经无法使用 // 尝试使用迭代器 - 已经无法使用
assertFalse(iterator.hasNext()); assertFalse(iterator.hasNext());
@ -252,13 +252,13 @@ public class ObjUtilTest {
@Test @Test
public void testLengthConsumesEnumeration() { public void testLengthConsumesEnumeration() {
Vector<String> vector = new Vector<>(Arrays.asList("a", "b", "c")); final Vector<String> vector = new Vector<>(Arrays.asList("a", "b", "c"));
Enumeration<String> enumeration = vector.elements(); final Enumeration<String> enumeration = vector.elements();
// 第一次调用length // 第一次调用length
int length1 = ObjUtil.length(enumeration); final int length1 = ObjUtil.length(enumeration);
assertEquals(3, length1); assertEquals(3, length1);
// 第二次调用length - 枚举已经被消耗 // 第二次调用length - 枚举已经被消耗
int length2 = ObjUtil.length(enumeration); final int length2 = ObjUtil.length(enumeration);
assertEquals(0, length2); assertEquals(0, length2);
// 枚举已经无法使用 // 枚举已经无法使用
assertFalse(enumeration.hasMoreElements()); assertFalse(enumeration.hasMoreElements());

View File

@ -13,7 +13,7 @@ public class TaskTableFactory {
* @param config 定时任务配置 * @param config 定时任务配置
* @return 任务表 * @return 任务表
*/ */
public static TaskTable create(CronConfig config) { public static TaskTable create(final CronConfig config) {
return config.isUseTriggerQueue() ? new TriggerQueueTaskTable() : new MatchTaskTable(); return config.isUseTriggerQueue() ? new TriggerQueueTaskTable() : new MatchTaskTable();
} }
} }

View File

@ -40,7 +40,7 @@ public class TriggerQueueTaskTable extends TaskTable {
} }
@Override @Override
public TriggerQueueTaskTable add(String id, CronPattern pattern, Task task) { public TriggerQueueTaskTable add(final String id, final CronPattern pattern, final Task task) {
super.add(id, pattern, task); super.add(id, pattern, task);
// 将下一个触发时间及任务添加到队列中 // 将下一个触发时间及任务添加到队列中
this.triggerQueue.offer(new TriggerTime(id, pattern.nextMatchFromNow())); this.triggerQueue.offer(new TriggerTime(id, pattern.nextMatchFromNow()));
@ -48,7 +48,7 @@ public class TriggerQueueTaskTable extends TaskTable {
} }
@Override @Override
public boolean remove(String id) { public boolean remove(final String id) {
// 移除队列中的任务 // 移除队列中的任务
this.triggerQueue.removeIf(task -> StrUtil.equals(task.id(), id)); this.triggerQueue.removeIf(task -> StrUtil.equals(task.id(), id));
return super.remove(id); return super.remove(id);
@ -56,7 +56,7 @@ public class TriggerQueueTaskTable extends TaskTable {
} }
@Override @Override
public boolean updatePattern(String id, CronPattern pattern) { public boolean updatePattern(final String id, final CronPattern pattern) {
// 移除队列中的任务 // 移除队列中的任务
this.triggerQueue.removeIf(task -> StrUtil.equals(task.id(), id)); this.triggerQueue.removeIf(task -> StrUtil.equals(task.id(), id));
// 将下一个触发时间及任务添加到队列中 // 将下一个触发时间及任务添加到队列中
@ -131,7 +131,7 @@ public class TriggerQueueTaskTable extends TaskTable {
*/ */
private record TriggerTime(String id, long timestamp) implements Comparable<TriggerTime> { private record TriggerTime(String id, long timestamp) implements Comparable<TriggerTime> {
@Override @Override
public int compareTo(TriggerTime other) { public int compareTo(final TriggerTime other) {
return Long.compare(this.timestamp, other.timestamp); return Long.compare(this.timestamp, other.timestamp);
} }
} }

View File

@ -193,7 +193,7 @@ public class CronPattern {
* @return 匹配到的下一个时间时间戳 * @return 匹配到的下一个时间时间戳
* @since 7.0.0 * @since 7.0.0
*/ */
public long nextMatch(long millis) { public long nextMatch(final long millis) {
return nextMatch(CalendarUtil.calendar(millis)).getTimeInMillis(); return nextMatch(CalendarUtil.calendar(millis)).getTimeInMillis();
} }

View File

@ -20,7 +20,7 @@ import cn.hutool.v7.core.lang.Console;
import cn.hutool.v7.cron.CronUtil; import cn.hutool.v7.cron.CronUtil;
public class SimpleDemo { public class SimpleDemo {
public static void main(String[] args) { public static void main(final String[] args) {
// 打开秒匹配 // 打开秒匹配
CronUtil.setMatchSecond(true); CronUtil.setMatchSecond(true);
// 添加任务 // 添加任务

View File

@ -5,7 +5,7 @@ import cn.hutool.v7.cron.CronConfig;
import cn.hutool.v7.cron.Scheduler; import cn.hutool.v7.cron.Scheduler;
public class TriggerQueueTest { public class TriggerQueueTest {
public static void main(String[] args) { public static void main(final String[] args) {
final Scheduler scheduler = new Scheduler(CronConfig.of().setMatchSecond(true).setUseTriggerQueue(true)); final Scheduler scheduler = new Scheduler(CronConfig.of().setMatchSecond(true).setUseTriggerQueue(true));
scheduler.schedule("*/10 * * * * *", scheduler.schedule("*/10 * * * * *",
() -> Console.log("Hutool task */10 running at: [{}]", System.currentTimeMillis())); () -> Console.log("Hutool task */10 running at: [{}]", System.currentTimeMillis()));

View File

@ -17,8 +17,8 @@
package cn.hutool.v7.cron.timingwheel; package cn.hutool.v7.cron.timingwheel;
public class Issue3090Test { public class Issue3090Test {
public static void main(String[] args) { public static void main(final String[] args) {
SystemTimer timer = new SystemTimer(); final SystemTimer timer = new SystemTimer();
timer.setDelayQueueTimeout(1000); timer.setDelayQueueTimeout(1000);
timer.start(); timer.start();
timer.addTask(new TimerTask(() -> { timer.addTask(new TimerTask(() -> {

View File

@ -211,7 +211,7 @@ public class Sign extends BaseAsymmetric<Sign> {
// If the certificate is of type X509Certificate, // If the certificate is of type X509Certificate,
// we should check whether it has a Key Usage // we should check whether it has a Key Usage
// extension marked as critical. // extension marked as critical.
if (certificate instanceof X509Certificate cert) { if (certificate instanceof final X509Certificate cert) {
// Check whether the cert has a key usage extension // Check whether the cert has a key usage extension
// marked as a critical extension. // marked as a critical extension.
// The OID for KeyUsage extension is 2.5.29.15. // The OID for KeyUsage extension is 2.5.29.15.

View File

@ -431,7 +431,7 @@ public class Entity extends Dict {
return SqlUtil.clobToStr((Clob) obj); return SqlUtil.clobToStr((Clob) obj);
} else if (obj instanceof Blob) { } else if (obj instanceof Blob) {
return SqlUtil.blobToStr((Blob) obj, charset); return SqlUtil.blobToStr((Blob) obj, charset);
} else if (obj instanceof RowId rowId) { } else if (obj instanceof final RowId rowId) {
return StrUtil.str(rowId.getBytes(), charset); return StrUtil.str(rowId.getBytes(), charset);
} }
return super.getStr(field, defaultValue); return super.getStr(field, defaultValue);

View File

@ -64,10 +64,10 @@ public class TomlConfigParser implements ConfigParser {
tomlContent = ResourceUtil.readUtf8Str(tomlPath); tomlContent = ResourceUtil.readUtf8Str(tomlPath);
} else { } else {
// 读取默认TOML文件 // 读取默认TOML文件
for (String defaultDbTomlPath : DEFAULT_DB_TOML_PATHS) { for (final String defaultDbTomlPath : DEFAULT_DB_TOML_PATHS) {
try { try {
tomlContent = ResourceUtil.readUtf8Str(defaultDbTomlPath); tomlContent = ResourceUtil.readUtf8Str(defaultDbTomlPath);
} catch (NoResourceException e) { } catch (final NoResourceException e) {
// ignore // ignore
} }
} }
@ -83,12 +83,12 @@ public class TomlConfigParser implements ConfigParser {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public DbConfig parse(final String group) { public DbConfig parse(final String group) {
Map<String, Object> groupData; final Map<String, Object> groupData;
if (StrUtil.isEmpty(group)) { if (StrUtil.isEmpty(group)) {
groupData = this.tomlData; groupData = this.tomlData;
} else { } else {
Object groupObj = this.tomlData.get(group); final Object groupObj = this.tomlData.get(group);
if (groupObj instanceof Map) { if (groupObj instanceof Map) {
// 新建一个Map避免继承属性影响原数据 // 新建一个Map避免继承属性影响原数据
groupData = new HashMap<>((Map<String, Object>) groupObj); groupData = new HashMap<>((Map<String, Object>) groupObj);
@ -109,7 +109,7 @@ public class TomlConfigParser implements ConfigParser {
/** /**
* 如果目标map中没有指定键则从全局配置复制 * 如果目标map中没有指定键则从全局配置复制
*/ */
private void copyPropertyIfAbsent(Map<String, Object> target, String key) { private void copyPropertyIfAbsent(final Map<String, Object> target, final String key) {
if (!target.containsKey(key) && this.tomlData.containsKey(key)) { if (!target.containsKey(key) && this.tomlData.containsKey(key)) {
target.put(key, this.tomlData.get(key)); target.put(key, this.tomlData.get(key));
} }
@ -118,9 +118,9 @@ public class TomlConfigParser implements ConfigParser {
/** /**
* 将TOML数据转换为DbConfig对象 * 将TOML数据转换为DbConfig对象
*/ */
private DbConfig toDbConfig(Map<String, Object> data) { private DbConfig toDbConfig(final Map<String, Object> data) {
// 基本信息 // 基本信息
String url = getAndRemoveString(data, DSKeys.KEY_ALIAS_URL); final String url = getAndRemoveString(data, DSKeys.KEY_ALIAS_URL);
if (StrUtil.isBlank(url)) { if (StrUtil.isBlank(url)) {
throw new DbException("No JDBC URL!"); throw new DbException("No JDBC URL!");
} }
@ -131,27 +131,27 @@ public class TomlConfigParser implements ConfigParser {
driver = DriverUtil.identifyDriver(url); driver = DriverUtil.identifyDriver(url);
} }
DbConfig dbConfig = DbConfig.of() final DbConfig dbConfig = DbConfig.of()
.setUrl(url) .setUrl(url)
.setDriver(driver) .setDriver(driver)
.setUser(getAndRemoveString(data, DSKeys.KEY_ALIAS_USER)) .setUser(getAndRemoveString(data, DSKeys.KEY_ALIAS_USER))
.setPass(getAndRemoveString(data, DSKeys.KEY_ALIAS_PASSWORD)); .setPass(getAndRemoveString(data, DSKeys.KEY_ALIAS_PASSWORD));
// SQL日志 // SQL日志
SqlLogFilter sqlLogFilter = getSqlLogFilter(data); final SqlLogFilter sqlLogFilter = getSqlLogFilter(data);
if (sqlLogFilter != null) { if (sqlLogFilter != null) {
dbConfig.addSqlFilter(sqlLogFilter); dbConfig.addSqlFilter(sqlLogFilter);
} }
// 大小写等配置 // 大小写等配置
Boolean caseInsensitive = getAndRemoveBoolean(data, DSKeys.KEY_CASE_INSENSITIVE); final Boolean caseInsensitive = getAndRemoveBoolean(data, DSKeys.KEY_CASE_INSENSITIVE);
if (null != caseInsensitive) { if (null != caseInsensitive) {
dbConfig.setCaseInsensitive(caseInsensitive); dbConfig.setCaseInsensitive(caseInsensitive);
} }
// 连接配置 // 连接配置
for (String key : DSKeys.KEY_CONN_PROPS) { for (final String key : DSKeys.KEY_CONN_PROPS) {
String connValue = getAndRemoveString(data, key); final String connValue = getAndRemoveString(data, key);
if (StrUtil.isNotBlank(connValue)) { if (StrUtil.isNotBlank(connValue)) {
dbConfig.addConnProps(key, connValue); dbConfig.addConnProps(key, connValue);
} }
@ -178,7 +178,7 @@ public class TomlConfigParser implements ConfigParser {
/** /**
* 获取SQL日志过滤器 * 获取SQL日志过滤器
*/ */
private SqlLogFilter getSqlLogFilter(Map<String, Object> data) { private SqlLogFilter getSqlLogFilter(final Map<String, Object> data) {
final Boolean isShowSql = getAndRemoveBoolean(data, DSKeys.KEY_SHOW_SQL); final Boolean isShowSql = getAndRemoveBoolean(data, DSKeys.KEY_SHOW_SQL);
if (isShowSql == null || !isShowSql) { if (isShowSql == null || !isShowSql) {
return null; return null;
@ -191,9 +191,9 @@ public class TomlConfigParser implements ConfigParser {
if (sqlLevelStr != null) { if (sqlLevelStr != null) {
sqlLevelStr = sqlLevelStr.toUpperCase(); sqlLevelStr = sqlLevelStr.toUpperCase();
} }
Level level = ConvertUtil.toEnum(Level.class, sqlLevelStr, Level.DEBUG); final Level level = ConvertUtil.toEnum(Level.class, sqlLevelStr, Level.DEBUG);
SqlLog sqlLog = new SqlLog(); final SqlLog sqlLog = new SqlLog();
sqlLog.init(true, isFormatSql, isShowParams, level); sqlLog.init(true, isFormatSql, isShowParams, level);
return new SqlLogFilter(sqlLog); return new SqlLogFilter(sqlLog);
@ -206,9 +206,9 @@ public class TomlConfigParser implements ConfigParser {
* @param keys 多个键 * @param keys 多个键
* @return 字符串值 * @return 字符串值
*/ */
private String getAndRemoveString(Map<String, Object> map, String... keys) { private String getAndRemoveString(final Map<String, Object> map, final String... keys) {
Object value = null; Object value = null;
for (String key : keys) { for (final String key : keys) {
value = map.remove(key); value = map.remove(key);
if (null != value) { if (null != value) {
break; break;
@ -224,9 +224,9 @@ public class TomlConfigParser implements ConfigParser {
* @param keys 多个键 * @param keys 多个键
* @return 布尔值 * @return 布尔值
*/ */
private Boolean getAndRemoveBoolean(Map<String, Object> map, String... keys) { private Boolean getAndRemoveBoolean(final Map<String, Object> map, final String... keys) {
Object value = null; Object value = null;
for (String key : keys) { for (final String key : keys) {
value = map.remove(key); value = map.remove(key);
if (null != value) { if (null != value) {
break; break;

View File

@ -1,183 +0,0 @@
package cn.hutool.v7.db.dialect;
import cn.hutool.v7.core.collection.CollUtil;
import cn.hutool.v7.core.lang.Assert;
import cn.hutool.v7.core.text.StrJoiner;
import cn.hutool.v7.core.text.StrUtil;
import cn.hutool.v7.db.meta.*;
import cn.hutool.v7.db.sql.QuoteWrapper;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public class DDLBuilder {
private QuoteWrapper quoteWrapper;
public String buildCreateTableSql(TableMeta tableMeta) {
StringBuilder sqlBuilder = new StringBuilder();
// 表名
final String tableName = tableMeta.getTableName();
Assert.notBlank(tableName, "Table name cannot be blank!");
buildCreateTableStart(sqlBuilder, tableName);
sqlBuilder.append(StrUtil.LF);
// 列定义
Collection<Column> columns = tableMeta.getColumns();
Assert.notEmpty(columns, "Table must have at least one column");
final String columnsDefinition = StrJoiner.of(",\n")
.append(columns, column -> " " + buildColumnDefinition(column)).toString();
sqlBuilder.append(columnsDefinition);
// 主键约束定义
buildPrimaryKey(sqlBuilder, tableMeta.getPkNames());
// 索引定义 (如果有)
List<IndexInfo> indexInfoList = tableMeta.getIndexInfoList();
if (CollUtil.isNotEmpty(indexInfoList)) {
for (IndexInfo indexInfo : indexInfoList) {
sqlBuilder.append(",\n ");
if (!indexInfo.isNonUnique()) {
sqlBuilder.append("UNIQUE ");
}
sqlBuilder.append("INDEX `").append(indexInfo.getIndexName()).append("` (");
// 遍历索引列信息列表
List<ColumnIndex> columnIndexInfoList = indexInfo.getColumnIndexInfoList();
if (columnIndexInfoList != null && !columnIndexInfoList.isEmpty()) {
boolean firstIndexColumn = true;
for (ColumnIndex columnIndex : columnIndexInfoList) {
if (!firstIndexColumn) {
sqlBuilder.append(", ");
}
sqlBuilder.append("`").append(columnIndex.getColumnName()).append("`");
// 可以添加排序信息如果需要的话
String ascOrDesc = columnIndex.getAscOrDesc();
if ("D".equalsIgnoreCase(ascOrDesc)) {
sqlBuilder.append(" DESC");
} else if ("A".equalsIgnoreCase(ascOrDesc)) {
sqlBuilder.append(" ASC");
}
firstIndexColumn = false;
}
}
sqlBuilder.append(")");
}
}
buildCreateTableEnd(sqlBuilder);
// 表注释
String remarks = tableMeta.getRemarks();
if (remarks != null && !remarks.isEmpty()) {
sqlBuilder.append(" COMMENT='").append(remarks.replace("'", "''")).append("'");
}
sqlBuilder.append(";");
return sqlBuilder.toString();
}
/**
* 通用方法建表开头可被子类重写如Oracle可能有特殊语法生成如<br>
* <pre>{@code
* CREATE TABLE <tableName> (
* }</pre>
*
* @param tableName 表名
*/
protected void buildCreateTableStart(StringBuilder sqlBuilder,String tableName) {
if (StrUtil.isBlank(tableName)) {
throw new IllegalArgumentException("Table name cannot be blank!");
}
sqlBuilder.append("CREATE TABLE ").append(wrap(tableName)).append(" (");
}
protected void buildPrimaryKey(StringBuilder sqlBuilder, Set<String> pkNames) {
if (pkNames.isEmpty()) {
return;
}
sqlBuilder.append(",\n PRIMARY KEY (");
boolean firstPk = true;
for (String pkName : pkNames) {
if (!firstPk) {
sqlBuilder.append(", ");
}
sqlBuilder.append(wrap(pkName));
firstPk = false;
}
sqlBuilder.append(")");
}
/**
* 根据Column对象生成列定义
* <p>
* 注意: 这里是一个简化的实现实际项目中需要根据Column类的具体属性
* 和数据库类型映射来完善
*
* @param column Column对象
* @return 列定义字符串
*/
private static String buildColumnDefinition(Column column) {
StringBuilder columnBuilder = new StringBuilder();
// 列名
columnBuilder.append("`").append(column.getName()).append("`");
// 数据类型 (这里假设Column有getTypeName方法)
// 实际应用中需要更复杂的类型映射
ColumnType type = column.getType();
if (type != null) {
columnBuilder.append(" ").append(type.getTypeName());
} else {
// 默认使用VARCHAR
columnBuilder.append(" VARCHAR(255)");
}
// 是否允许为空 (假设Column有isNullable方法)
if (!column.isNullable()) {
columnBuilder.append(" NOT NULL");
}
// 默认值 (假设Column有getDefaultValue方法)
String defaultValue = column.getColumnDef();
if (defaultValue != null) {
columnBuilder.append(" DEFAULT '").append(defaultValue.replace("'", "''")).append("'");
}
// 注释 (假设Column有getRemarks方法)
String remarks = column.getRemarks();
if (remarks != null && !remarks.isEmpty()) {
columnBuilder.append(" COMMENT '").append(remarks.replace("'", "''")).append("'");
}
return columnBuilder.toString();
}
/**
* 通用方法建表结尾可被子类重写如MySQL可能有特殊语法生成如<br>
* <pre>{@code
* )
* }</pre>
*/
protected void buildCreateTableEnd(StringBuilder sqlBuilder) {
sqlBuilder.append("\n)");
}
/**
* 字段名包装
*
* @param field 字段名
* @return 包装后的字段名
*/
private String wrap(String field) {
if (null != quoteWrapper) {
return quoteWrapper.wrap(field);
}
return field;
}
}

Some files were not shown because too many files have changed in this diff Show More