mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-12-06 09:09:10 +08:00
Compare commits
10 Commits
e554eba399
...
fceeafebce
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fceeafebce | ||
|
|
12c86e5bab | ||
|
|
f95c3ff165 | ||
|
|
342050aab6 | ||
|
|
3e83b6004f | ||
|
|
7578350baa | ||
|
|
dbed4a4d0f | ||
|
|
3f15fdd44c | ||
|
|
1bba40a32f | ||
|
|
7e8fd78377 |
@ -193,7 +193,18 @@ public class Models {
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ public interface AIService {
|
||||
* @return AI回答
|
||||
* @since 6.0.0
|
||||
*/
|
||||
default String chat(String prompt){
|
||||
default String chat(final String prompt){
|
||||
final List<Message> messages = new ArrayList<>();
|
||||
messages.add(new Message("system", "You are a helpful assistant"));
|
||||
messages.add(new Message("user", prompt));
|
||||
@ -48,7 +48,7 @@ public interface AIService {
|
||||
* @param callback 流式数据回调函数
|
||||
* @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<>();
|
||||
messages.add(new Message("system", "You are a helpful assistant"));
|
||||
messages.add(new Message("user", prompt));
|
||||
|
||||
@ -63,8 +63,8 @@ public class DeepSeekServiceImpl extends BaseAIService implements DeepSeekServic
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chat(List<Message> messages, Consumer<String> callback) {
|
||||
Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
|
||||
public void chat(final List<Message> messages, final Consumer<String> callback) {
|
||||
final Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
|
||||
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "deepseek-chat-sse").start();
|
||||
}
|
||||
|
||||
@ -76,8 +76,8 @@ public class DeepSeekServiceImpl extends BaseAIService implements DeepSeekServic
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beta(String prompt, Consumer<String> callback) {
|
||||
Map<String, Object> paramMap = buildBetaStreamRequestBody(prompt);
|
||||
public void beta(final String prompt, final Consumer<String> callback) {
|
||||
final Map<String, Object> paramMap = buildBetaStreamRequestBody(prompt);
|
||||
ThreadUtil.newThread(() -> sendPostStream(BETA_ENDPOINT, paramMap, callback), "deepseek-beta-sse").start();
|
||||
}
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ public interface DoubaoService extends AIService {
|
||||
* @return AI回答
|
||||
* @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());
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ public interface DoubaoService extends AIService {
|
||||
* @param callback 流式数据回调函数
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ public interface DoubaoService extends AIService {
|
||||
* @return 生成任务id
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ public interface DoubaoService extends AIService {
|
||||
* @return AI回答
|
||||
* @since 6.0.0
|
||||
*/
|
||||
default String batchChat(String prompt){
|
||||
default String batchChat(final String prompt){
|
||||
final List<Message> messages = new ArrayList<>();
|
||||
messages.add(new Message("system", "You are a helpful assistant"));
|
||||
messages.add(new Message("user", prompt));
|
||||
@ -218,7 +218,7 @@ public interface DoubaoService extends AIService {
|
||||
* @return AI的回答
|
||||
* @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<>();
|
||||
messages.add(new Message("user", prompt));
|
||||
return chatContext(messages, contextId);
|
||||
@ -233,7 +233,7 @@ public interface DoubaoService extends AIService {
|
||||
* @param callback 流式数据回调函数
|
||||
* @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<>();
|
||||
messages.add(new Message("user", prompt));
|
||||
chatContext(messages, contextId, callback);
|
||||
|
||||
@ -44,7 +44,7 @@ public class GrokCommon {
|
||||
|
||||
private final String detail;
|
||||
|
||||
GrokVision(String detail) {
|
||||
GrokVision(final String detail) {
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ public class GrokConfig extends BaseAIConfig {
|
||||
*
|
||||
* @param apiKey API密钥
|
||||
*/
|
||||
public GrokConfig(String apiKey) {
|
||||
public GrokConfig(final String apiKey) {
|
||||
this();
|
||||
setApiKey(apiKey);
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ public interface GrokService extends AIService {
|
||||
* @return AI回答
|
||||
* @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<>();
|
||||
messages.add(new Message("system", "You are a helpful assistant"));
|
||||
@ -55,7 +55,7 @@ public interface GrokService extends AIService {
|
||||
* @param callback 流式数据回调函数
|
||||
* @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<>();
|
||||
messages.add(new Message("system", "You are a helpful assistant"));
|
||||
messages.add(new Message("user", prompt));
|
||||
@ -112,7 +112,7 @@ public interface GrokService extends AIService {
|
||||
* @return AI回答
|
||||
* @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());
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ public interface GrokService extends AIService {
|
||||
* @param callback 流式数据回调函数
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
@ -64,84 +64,84 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
|
||||
|
||||
@Override
|
||||
public String chat(final List<Message> messages) {
|
||||
String paramJson = buildChatRequestBody(messages);
|
||||
Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
final String paramJson = buildChatRequestBody(messages);
|
||||
final Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chat(List<Message> messages, Consumer<String> callback) {
|
||||
Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
|
||||
public void chat(final List<Message> messages, final Consumer<String> callback) {
|
||||
final Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
|
||||
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "grok-chat-sse").start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String message(final List<Message> messages, int maxToken) {
|
||||
String paramJson = buildMessageRequestBody(messages, maxToken);
|
||||
Response response = sendPost(MESSAGES, paramJson);
|
||||
public String message(final List<Message> messages, final int maxToken) {
|
||||
final String paramJson = buildMessageRequestBody(messages, maxToken);
|
||||
final Response response = sendPost(MESSAGES, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void message(List<Message> messages, int maxToken, final Consumer<String> callback) {
|
||||
Map<String, Object> paramMap = buildMessageStreamRequestBody(messages, maxToken);
|
||||
public void message(final List<Message> messages, final int maxToken, final Consumer<String> callback) {
|
||||
final Map<String, Object> paramMap = buildMessageStreamRequestBody(messages, maxToken);
|
||||
ThreadUtil.newThread(() -> sendPostStream(MESSAGES, paramMap, callback), "grok-message-sse").start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chatVision(String prompt, final List<String> images, String detail) {
|
||||
String paramJson = buildChatVisionRequestBody(prompt, images, detail);
|
||||
Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
public String chatVision(final String prompt, final List<String> images, final String detail) {
|
||||
final String paramJson = buildChatVisionRequestBody(prompt, images, detail);
|
||||
final Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chatVision(String prompt, List<String> images, String detail, Consumer<String> callback) {
|
||||
Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail);
|
||||
public void chatVision(final String prompt, final List<String> images, final String detail, final Consumer<String> callback) {
|
||||
final Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail);
|
||||
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "grok-chatVision-sse").start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String models() {
|
||||
Response response = sendGet(MODELS_ENDPOINT);
|
||||
final Response response = sendGet(MODELS_ENDPOINT);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModel(String modelId) {
|
||||
Response response = sendGet(MODELS_ENDPOINT + "/" + modelId);
|
||||
public String getModel(final String modelId) {
|
||||
final Response response = sendGet(MODELS_ENDPOINT + "/" + modelId);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String languageModels() {
|
||||
Response response = sendGet(LANGUAGE_MODELS);
|
||||
final Response response = sendGet(LANGUAGE_MODELS);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguageModel(String modelId) {
|
||||
Response response = sendGet(LANGUAGE_MODELS + "/" + modelId);
|
||||
public String getLanguageModel(final String modelId) {
|
||||
final Response response = sendGet(LANGUAGE_MODELS + "/" + modelId);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tokenizeText(String text) {
|
||||
String paramJson = buildTokenizeRequestBody(text);
|
||||
Response response = sendPost(TOKENIZE_TEXT, paramJson);
|
||||
public String tokenizeText(final String text) {
|
||||
final String paramJson = buildTokenizeRequestBody(text);
|
||||
final Response response = sendPost(TOKENIZE_TEXT, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deferredCompletion(String requestId) {
|
||||
Response response = sendGet(DEFERRED_COMPLETION + "/" + requestId);
|
||||
public String deferredCompletion(final String requestId) {
|
||||
final Response response = sendGet(DEFERRED_COMPLETION + "/" + requestId);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String imagesGenerations(String prompt) {
|
||||
String paramJson = buildImagesGenerationsRequestBody(prompt);
|
||||
Response response = sendPost(IMAGES_GENERATIONS, paramJson);
|
||||
public String imagesGenerations(final String prompt) {
|
||||
final String paramJson = buildImagesGenerationsRequestBody(prompt);
|
||||
final Response response = sendPost(IMAGES_GENERATIONS, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@ -170,7 +170,7 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
|
||||
}
|
||||
|
||||
//构建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<Object> content = new ArrayList<>();
|
||||
@ -179,10 +179,10 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
|
||||
contentMap.put("type", "text");
|
||||
contentMap.put("text", prompt);
|
||||
content.add(contentMap);
|
||||
for (String img : images) {
|
||||
HashMap<String, Object> imgUrlMap = new HashMap<>();
|
||||
for (final String img : images) {
|
||||
final HashMap<String, Object> imgUrlMap = new HashMap<>();
|
||||
imgUrlMap.put("type", "image_url");
|
||||
HashMap<String, String> urlMap = new HashMap<>();
|
||||
final HashMap<String, String> urlMap = new HashMap<>();
|
||||
urlMap.put("url", img);
|
||||
urlMap.put("detail", detail);
|
||||
imgUrlMap.put("image_url", urlMap);
|
||||
@ -200,7 +200,7 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
|
||||
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<Object> content = new ArrayList<>();
|
||||
@ -209,10 +209,10 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
|
||||
contentMap.put("type", "text");
|
||||
contentMap.put("text", prompt);
|
||||
content.add(contentMap);
|
||||
for (String img : images) {
|
||||
HashMap<String, Object> imgUrlMap = new HashMap<>();
|
||||
for (final String img : images) {
|
||||
final HashMap<String, Object> imgUrlMap = new HashMap<>();
|
||||
imgUrlMap.put("type", "image_url");
|
||||
HashMap<String, String> urlMap = new HashMap<>();
|
||||
final HashMap<String, String> urlMap = new HashMap<>();
|
||||
urlMap.put("url", img);
|
||||
urlMap.put("detail", detail);
|
||||
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<>();
|
||||
paramMap.put("model", config.getModel());
|
||||
paramMap.put("messages", messages);
|
||||
@ -243,7 +243,7 @@ public class GrokServiceImpl extends BaseAIService implements GrokService {
|
||||
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<>();
|
||||
paramMap.put("stream", true);
|
||||
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工具
|
||||
final Map<String, Object> paramMap = new HashMap<>();
|
||||
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<>();
|
||||
paramMap.put("model", config.getModel());
|
||||
paramMap.put("prompt", prompt);
|
||||
|
||||
@ -33,7 +33,7 @@ public class HutoolCommon {
|
||||
|
||||
private final String detail;
|
||||
|
||||
HutoolVision(String detail) {
|
||||
HutoolVision(final String detail) {
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ public class HutoolCommon {
|
||||
|
||||
private final String voice;
|
||||
|
||||
HutoolSpeech(String voice) {
|
||||
HutoolSpeech(final String voice) {
|
||||
this.voice = voice;
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ public class HutoolCommon {
|
||||
private final String type;
|
||||
private final Object value;
|
||||
|
||||
HutoolVideo(String type, Object value) {
|
||||
HutoolVideo(final String type, final Object value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ public class HutoolConfig extends BaseAIConfig {
|
||||
setModel(DEFAULT_MODEL);
|
||||
}
|
||||
|
||||
public HutoolConfig(String apiKey) {
|
||||
public HutoolConfig(final String apiKey) {
|
||||
this();
|
||||
setApiKey(apiKey);
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ public interface HutoolService extends AIService {
|
||||
* @return AI回答
|
||||
* @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());
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ public interface HutoolService extends AIService {
|
||||
* @param callback 流式数据回调函数
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ public interface HutoolService extends AIService {
|
||||
* @return 返回的音频mp3文件流
|
||||
* @since 6.0.0
|
||||
*/
|
||||
default InputStream tts(String input) {
|
||||
default InputStream tts(final String input) {
|
||||
return tts(input, HutoolCommon.HutoolSpeech.ALLOY);
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ public interface HutoolService extends AIService {
|
||||
* @return 生成任务id
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
@ -63,69 +63,69 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
|
||||
|
||||
@Override
|
||||
public String chat(final List<Message> messages) {
|
||||
String paramJson = buildChatRequestBody(messages);
|
||||
Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
final String paramJson = buildChatRequestBody(messages);
|
||||
final Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chat(List<Message> messages,Consumer<String> callback) {
|
||||
Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
|
||||
public void chat(final List<Message> messages, final Consumer<String> callback) {
|
||||
final Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
|
||||
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "hutool-chat-sse").start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chatVision(String prompt, final List<String> images, String detail) {
|
||||
String paramJson = buildChatVisionRequestBody(prompt, images, detail);
|
||||
Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
public String chatVision(final String prompt, final List<String> images, final String detail) {
|
||||
final String paramJson = buildChatVisionRequestBody(prompt, images, detail);
|
||||
final Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chatVision(String prompt, List<String> images, String detail, Consumer<String> callback) {
|
||||
Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail);
|
||||
public void chatVision(final String prompt, final List<String> images, final String detail, final Consumer<String> callback) {
|
||||
final Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail);
|
||||
System.out.println(JSONUtil.toJsonStr(paramMap));
|
||||
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "hutool-chatVision-sse").start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tokenizeText(String text) {
|
||||
String paramJson = buildTokenizeRequestBody(text);
|
||||
Response response = sendPost(TOKENIZE_TEXT, paramJson);
|
||||
public String tokenizeText(final String text) {
|
||||
final String paramJson = buildTokenizeRequestBody(text);
|
||||
final Response response = sendPost(TOKENIZE_TEXT, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String imagesGenerations(String prompt) {
|
||||
String paramJson = buildImagesGenerationsRequestBody(prompt);
|
||||
Response response = sendPost(IMAGES_GENERATIONS, paramJson);
|
||||
public String imagesGenerations(final String prompt) {
|
||||
final String paramJson = buildImagesGenerationsRequestBody(prompt);
|
||||
final Response response = sendPost(IMAGES_GENERATIONS, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String embeddingVision(String text, String image) {
|
||||
String paramJson = buildEmbeddingVisionRequestBody(text, image);
|
||||
Response response = sendPost(EMBEDDING_VISION, paramJson);
|
||||
public String embeddingVision(final String text, final String image) {
|
||||
final String paramJson = buildEmbeddingVisionRequestBody(text, image);
|
||||
final Response response = sendPost(EMBEDDING_VISION, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream tts(String input, final HutoolCommon.HutoolSpeech voice) {
|
||||
public InputStream tts(final String input, final HutoolCommon.HutoolSpeech voice) {
|
||||
try {
|
||||
String paramJson = buildTTSRequestBody(input, voice.getVoice());
|
||||
Response response = sendPost(TTS, paramJson);
|
||||
final String paramJson = buildTTSRequestBody(input, voice.getVoice());
|
||||
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")) {
|
||||
// 如果是JSON响应,说明有错误
|
||||
String errorBody = response.bodyStr();
|
||||
final String errorBody = response.bodyStr();
|
||||
throw new AIException("TTS请求失败: " + errorBody);
|
||||
}
|
||||
// 默认返回音频流
|
||||
return response.bodyStream();
|
||||
} catch (Exception e) {
|
||||
} catch (final Exception e) {
|
||||
throw new AIException("TTS处理失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
@ -133,21 +133,21 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
|
||||
@Override
|
||||
public String stt(final File file) {
|
||||
final Map<String, Object> paramMap = buildSTTRequestBody(file);
|
||||
Response response = sendFormData(STT, paramMap);
|
||||
final Response response = sendFormData(STT, paramMap);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String videoTasks(String text, String image, final List<HutoolCommon.HutoolVideo> videoParams) {
|
||||
String paramJson = buildGenerationsTasksRequestBody(text, image, videoParams);
|
||||
Response response = sendPost(CREATE_VIDEO, paramJson);
|
||||
public String videoTasks(final String text, final String image, final List<HutoolCommon.HutoolVideo> videoParams) {
|
||||
final String paramJson = buildGenerationsTasksRequestBody(text, image, videoParams);
|
||||
final Response response = sendPost(CREATE_VIDEO, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVideoTasksInfo(String taskId) {
|
||||
Response response = sendGet(CREATE_VIDEO + "/" + taskId);
|
||||
public String getVideoTasksInfo(final String taskId) {
|
||||
final Response response = sendGet(CREATE_VIDEO + "/" + taskId);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
|
||||
}
|
||||
|
||||
//构建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<Object> content = new ArrayList<>();
|
||||
@ -186,10 +186,10 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
|
||||
contentMap.put("type", "text");
|
||||
contentMap.put("text", prompt);
|
||||
content.add(contentMap);
|
||||
for (String img : images) {
|
||||
HashMap<String, Object> imgUrlMap = new HashMap<>();
|
||||
for (final String img : images) {
|
||||
final HashMap<String, Object> imgUrlMap = new HashMap<>();
|
||||
imgUrlMap.put("type", "image_url");
|
||||
HashMap<String, String> urlMap = new HashMap<>();
|
||||
final HashMap<String, String> urlMap = new HashMap<>();
|
||||
urlMap.put("url", img);
|
||||
urlMap.put("detail", detail);
|
||||
imgUrlMap.put("image_url", urlMap);
|
||||
@ -207,7 +207,7 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
|
||||
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<Object> content = new ArrayList<>();
|
||||
@ -216,10 +216,10 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
|
||||
contentMap.put("type", "text");
|
||||
contentMap.put("text", prompt);
|
||||
content.add(contentMap);
|
||||
for (String img : images) {
|
||||
HashMap<String, Object> imgUrlMap = new HashMap<>();
|
||||
for (final String img : images) {
|
||||
final HashMap<String, Object> imgUrlMap = new HashMap<>();
|
||||
imgUrlMap.put("type", "image_url");
|
||||
HashMap<String, String> urlMap = new HashMap<>();
|
||||
final HashMap<String, String> urlMap = new HashMap<>();
|
||||
urlMap.put("url", img);
|
||||
urlMap.put("detail", detail);
|
||||
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工具
|
||||
final Map<String, Object> paramMap = new HashMap<>();
|
||||
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<>();
|
||||
paramMap.put("model", config.getModel());
|
||||
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工具
|
||||
final Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("model", config.getModel());
|
||||
@ -295,7 +295,7 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
|
||||
|
||||
|
||||
//构建TTS请求体
|
||||
private String buildTTSRequestBody(String input, String voice) {
|
||||
private String buildTTSRequestBody(final String input, final String voice) {
|
||||
final Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("model", config.getModel());
|
||||
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工具
|
||||
final Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("model", config.getModel());
|
||||
@ -345,9 +345,9 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
|
||||
if (videoParams != null && !videoParams.isEmpty()) {
|
||||
//如果有文本参数就加在后面
|
||||
if (textMap != null && !textMap.isEmpty()) {
|
||||
int textIndex = content.indexOf(textMap);
|
||||
StringBuilder textBuilder = new StringBuilder(text);
|
||||
for (HutoolCommon.HutoolVideo videoParam : videoParams) {
|
||||
final int textIndex = content.indexOf(textMap);
|
||||
final StringBuilder textBuilder = new StringBuilder(text);
|
||||
for (final HutoolCommon.HutoolVideo videoParam : videoParams) {
|
||||
textBuilder.append(" ").append(videoParam.getType()).append(" ").append(videoParam.getValue());
|
||||
}
|
||||
textMap.put("type", "text");
|
||||
@ -360,8 +360,8 @@ public class HutoolServiceImpl extends BaseAIService implements HutoolService {
|
||||
}
|
||||
} else {
|
||||
//如果没有文本参数就重新增加
|
||||
StringBuilder textBuilder = new StringBuilder();
|
||||
for (HutoolCommon.HutoolVideo videoParam : videoParams) {
|
||||
final StringBuilder textBuilder = new StringBuilder();
|
||||
for (final HutoolCommon.HutoolVideo videoParam : videoParams) {
|
||||
textBuilder.append(videoParam.getType()).append(videoParam.getValue()).append(" ");
|
||||
}
|
||||
textMap.put("type", "text");
|
||||
|
||||
@ -39,7 +39,7 @@ public class OllamaCommon {
|
||||
|
||||
private final String format;
|
||||
|
||||
OllamaFormat(String format) {
|
||||
OllamaFormat(final String format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
|
||||
@ -36,12 +36,12 @@ public class OllamaConfig extends BaseAIConfig {
|
||||
setModel(DEFAULT_MODEL);
|
||||
}
|
||||
|
||||
public OllamaConfig(String apiUrl) {
|
||||
public OllamaConfig(final String apiUrl) {
|
||||
this();
|
||||
setApiUrl(apiUrl);
|
||||
}
|
||||
|
||||
public OllamaConfig(String apiUrl, String model) {
|
||||
public OllamaConfig(final String apiUrl, final String model) {
|
||||
this();
|
||||
setApiUrl(apiUrl);
|
||||
setModel(model);
|
||||
|
||||
@ -130,7 +130,7 @@ public interface OllamaService extends AIService {
|
||||
* @return AI回答
|
||||
* @since 5.8.40
|
||||
*/
|
||||
default String chat(String prompt) {
|
||||
default String chat(final String prompt) {
|
||||
final List<Message> messages = new ArrayList<>();
|
||||
messages.add(new Message("user", prompt));
|
||||
return chat(messages);
|
||||
@ -143,7 +143,7 @@ public interface OllamaService extends AIService {
|
||||
* @param callback 流式数据回调函数
|
||||
* @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<>();
|
||||
messages.add(new Message("user", prompt));
|
||||
chat(messages, callback);
|
||||
|
||||
@ -33,7 +33,7 @@ public class OpenaiCommon {
|
||||
|
||||
private final String effort;
|
||||
|
||||
OpenaiReasoning(String effort) {
|
||||
OpenaiReasoning(final String effort) {
|
||||
this.effort = effort;
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ public class OpenaiCommon {
|
||||
|
||||
private final String detail;
|
||||
|
||||
OpenaiVision(String detail) {
|
||||
OpenaiVision(final String detail) {
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ public class OpenaiCommon {
|
||||
|
||||
private final String voice;
|
||||
|
||||
OpenaiSpeech(String voice) {
|
||||
OpenaiSpeech(final String voice) {
|
||||
this.voice = voice;
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ public class OpenaiConfig extends BaseAIConfig {
|
||||
setModel(DEFAULT_MODEL);
|
||||
}
|
||||
|
||||
public OpenaiConfig(String apiKey) {
|
||||
public OpenaiConfig(final String apiKey) {
|
||||
this();
|
||||
setApiKey(apiKey);
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ public interface OpenaiService extends AIService {
|
||||
* @return AI回答
|
||||
* @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());
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ public interface OpenaiService extends AIService {
|
||||
* @param callback 流式数据回调函数
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ public interface OpenaiService extends AIService {
|
||||
* @return 包含生成图片的url
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ public interface OpenaiService extends AIService {
|
||||
* @return 返回的音频mp3文件流
|
||||
* @since 6.0.0
|
||||
*/
|
||||
default InputStream textToSpeech(String input) {
|
||||
default InputStream textToSpeech(final String input) {
|
||||
return textToSpeech(input, OpenaiCommon.OpenaiSpeech.ALLOY);
|
||||
}
|
||||
|
||||
@ -178,7 +178,7 @@ public interface OpenaiService extends AIService {
|
||||
* @return AI返回结果
|
||||
* @since 6.0.0
|
||||
*/
|
||||
default String moderations(String text) {
|
||||
default String moderations(final String text) {
|
||||
return moderations(text, null);
|
||||
}
|
||||
|
||||
@ -191,7 +191,7 @@ public interface OpenaiService extends AIService {
|
||||
* @return AI回答
|
||||
* @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<>();
|
||||
messages.add(new Message("system", "You are a helpful assistant"));
|
||||
messages.add(new Message("user", prompt));
|
||||
@ -207,7 +207,7 @@ public interface OpenaiService extends AIService {
|
||||
* @param callback 流式数据回调函数
|
||||
* @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<>();
|
||||
messages.add(new Message("system", "You are a helpful assistant"));
|
||||
messages.add(new Message("user", prompt));
|
||||
@ -222,7 +222,7 @@ public interface OpenaiService extends AIService {
|
||||
* @return AI回答
|
||||
* @since 6.0.0
|
||||
*/
|
||||
default String chatReasoning(String prompt) {
|
||||
default String chatReasoning(final String prompt) {
|
||||
return chatReasoning(prompt, OpenaiCommon.OpenaiReasoning.MEDIUM.getEffort());
|
||||
}
|
||||
|
||||
@ -234,7 +234,7 @@ public interface OpenaiService extends AIService {
|
||||
* @param callback 流式数据回调函数
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
@ -64,89 +64,89 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
|
||||
|
||||
@Override
|
||||
public String chat(final List<Message> messages) {
|
||||
String paramJson = buildChatRequestBody(messages);
|
||||
Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
final String paramJson = buildChatRequestBody(messages);
|
||||
final Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chat(List<Message> messages, Consumer<String> callback) {
|
||||
Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
|
||||
public void chat(final List<Message> messages, final Consumer<String> callback) {
|
||||
final Map<String, Object> paramMap = buildChatStreamRequestBody(messages);
|
||||
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "openai-chat-sse").start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chatVision(String prompt, final List<String> images, String detail) {
|
||||
String paramJson = buildChatVisionRequestBody(prompt, images, detail);
|
||||
Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
public String chatVision(final String prompt, final List<String> images, final String detail) {
|
||||
final String paramJson = buildChatVisionRequestBody(prompt, images, detail);
|
||||
final Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chatVision(String prompt, List<String> images, String detail, Consumer<String> callback) {
|
||||
Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail);
|
||||
public void chatVision(final String prompt, final List<String> images, final String detail, final Consumer<String> callback) {
|
||||
final Map<String, Object> paramMap = buildChatVisionStreamRequestBody(prompt, images, detail);
|
||||
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "openai-chatVision-sse").start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String imagesGenerations(String prompt) {
|
||||
String paramJson = buildImagesGenerationsRequestBody(prompt);
|
||||
Response response = sendPost(IMAGES_GENERATIONS, paramJson);
|
||||
public String imagesGenerations(final String prompt) {
|
||||
final String paramJson = buildImagesGenerationsRequestBody(prompt);
|
||||
final Response response = sendPost(IMAGES_GENERATIONS, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@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);
|
||||
Response response = sendFormData(IMAGES_EDITS, paramMap);
|
||||
final Response response = sendFormData(IMAGES_EDITS, paramMap);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String imagesVariations(final File image) {
|
||||
final Map<String, Object> paramMap = buildImagesVariationsRequestBody(image);
|
||||
Response response = sendFormData(IMAGES_VARIATIONS, paramMap);
|
||||
final Response response = sendFormData(IMAGES_VARIATIONS, paramMap);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream textToSpeech(String input, final OpenaiCommon.OpenaiSpeech voice) {
|
||||
String paramJson = buildTTSRequestBody(input, voice.getVoice());
|
||||
Response response = sendPost(TTS, paramJson);
|
||||
public InputStream textToSpeech(final String input, final OpenaiCommon.OpenaiSpeech voice) {
|
||||
final String paramJson = buildTTSRequestBody(input, voice.getVoice());
|
||||
final Response response = sendPost(TTS, paramJson);
|
||||
return response.bodyStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String speechToText(final File file) {
|
||||
final Map<String, Object> paramMap = buildSTTRequestBody(file);
|
||||
Response response = sendFormData(STT, paramMap);
|
||||
final Response response = sendFormData(STT, paramMap);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String embeddingText(String input) {
|
||||
String paramJson = buildEmbeddingTextRequestBody(input);
|
||||
Response response = sendPost(EMBEDDINGS, paramJson);
|
||||
public String embeddingText(final String input) {
|
||||
final String paramJson = buildEmbeddingTextRequestBody(input);
|
||||
final Response response = sendPost(EMBEDDINGS, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String moderations(String text, String imgUrl) {
|
||||
String paramJson = buileModerationsRequestBody(text, imgUrl);
|
||||
Response response = sendPost(MODERATIONS, paramJson);
|
||||
public String moderations(final String text, final String imgUrl) {
|
||||
final String paramJson = buileModerationsRequestBody(text, imgUrl);
|
||||
final Response response = sendPost(MODERATIONS, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chatReasoning(final List<Message> messages, String reasoningEffort) {
|
||||
String paramJson = buildChatReasoningRequestBody(messages, reasoningEffort);
|
||||
Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
public String chatReasoning(final List<Message> messages, final String reasoningEffort) {
|
||||
final String paramJson = buildChatReasoningRequestBody(messages, reasoningEffort);
|
||||
final Response response = sendPost(CHAT_ENDPOINT, paramJson);
|
||||
return response.bodyStr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chatReasoning(List<Message> messages, String reasoningEffort, Consumer<String> callback) {
|
||||
Map<String, Object> paramMap = buildChatReasoningStreamRequestBody(messages, reasoningEffort);
|
||||
public void chatReasoning(final List<Message> messages, final String reasoningEffort, final Consumer<String> callback) {
|
||||
final Map<String, Object> paramMap = buildChatReasoningStreamRequestBody(messages, reasoningEffort);
|
||||
ThreadUtil.newThread(() -> sendPostStream(CHAT_ENDPOINT, paramMap, callback), "openai-chatReasoning-sse").start();
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
|
||||
}
|
||||
|
||||
//构建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<Object> content = new ArrayList<>();
|
||||
@ -184,7 +184,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
|
||||
contentMap.put("type", "text");
|
||||
contentMap.put("text", prompt);
|
||||
content.add(contentMap);
|
||||
for (String img : images) {
|
||||
for (final String img : images) {
|
||||
final Map<String, Object> imgUrlMap = new HashMap<>();
|
||||
imgUrlMap.put("type", "image_url");
|
||||
final Map<String, String> urlMap = new HashMap<>();
|
||||
@ -205,7 +205,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
|
||||
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<Object> content = new ArrayList<>();
|
||||
@ -214,10 +214,10 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
|
||||
contentMap.put("type", "text");
|
||||
contentMap.put("text", prompt);
|
||||
content.add(contentMap);
|
||||
for (String img : images) {
|
||||
HashMap<String, Object> imgUrlMap = new HashMap<>();
|
||||
for (final String img : images) {
|
||||
final HashMap<String, Object> imgUrlMap = new HashMap<>();
|
||||
imgUrlMap.put("type", "image_url");
|
||||
HashMap<String, String> urlMap = new HashMap<>();
|
||||
final HashMap<String, String> urlMap = new HashMap<>();
|
||||
urlMap.put("url", img);
|
||||
urlMap.put("detail", detail);
|
||||
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<>();
|
||||
paramMap.put("model", config.getModel());
|
||||
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<>();
|
||||
paramMap.put("model", config.getModel());
|
||||
paramMap.put("prompt", prompt);
|
||||
@ -274,7 +274,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
|
||||
}
|
||||
|
||||
//构建TTS请求体
|
||||
private String buildTTSRequestBody(String input, String voice) {
|
||||
private String buildTTSRequestBody(final String input, final String voice) {
|
||||
final Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("model", config.getModel());
|
||||
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工具
|
||||
final Map<String, Object> paramMap = new HashMap<>();
|
||||
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工具
|
||||
final Map<String, Object> paramMap = new HashMap<>();
|
||||
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<>();
|
||||
paramMap.put("model", config.getModel());
|
||||
paramMap.put("messages", messages);
|
||||
@ -350,7 +350,7 @@ public class OpenaiServiceImpl extends BaseAIService implements OpenaiService {
|
||||
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<>();
|
||||
paramMap.put("stream", true);
|
||||
paramMap.put("model", config.getModel());
|
||||
|
||||
@ -45,9 +45,9 @@ class DeepSeekServiceTest {
|
||||
@Test
|
||||
@Disabled
|
||||
void chatStream() {
|
||||
String prompt = "写一个疯狂星期四广告词";
|
||||
final String prompt = "写一个疯狂星期四广告词";
|
||||
// 使用AtomicBoolean作为结束标志
|
||||
AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
|
||||
deepSeekService.chat(prompt, data -> {
|
||||
assertNotNull(data);
|
||||
@ -85,9 +85,9 @@ class DeepSeekServiceTest {
|
||||
@Test
|
||||
@Disabled
|
||||
void betaStream() {
|
||||
String beta = "写一个疯狂星期四广告词";
|
||||
final String beta = "写一个疯狂星期四广告词";
|
||||
// 使用AtomicBoolean作为结束标志
|
||||
AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
|
||||
deepSeekService.beta(beta, data -> {
|
||||
assertNotNull(data);
|
||||
|
||||
@ -48,9 +48,9 @@ class DoubaoServiceTest {
|
||||
@Test
|
||||
@Disabled
|
||||
void chatStream() {
|
||||
String prompt = "写一个疯狂星期四广告词";
|
||||
final String prompt = "写一个疯狂星期四广告词";
|
||||
// 使用AtomicBoolean作为结束标志
|
||||
AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
|
||||
doubaoService.chat(prompt, data -> {
|
||||
assertNotNull(data);
|
||||
@ -94,11 +94,11 @@ class DoubaoServiceTest {
|
||||
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);
|
||||
|
||||
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 String prompt = "图片上有些什么?";
|
||||
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 isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
doubaoService.chatVision(prompt,images, data -> {
|
||||
assertNotNull(data);
|
||||
if (data.contains("[DONE]")) {
|
||||
@ -184,7 +184,7 @@ class DoubaoServiceTest {
|
||||
messages.add(new Message("user","你想做些什么"));
|
||||
|
||||
// 使用AtomicBoolean作为结束标志
|
||||
AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
doubaoService.botsChat(messages, data -> {
|
||||
assertNotNull(data);
|
||||
if (data.contains("[DONE]")) {
|
||||
@ -278,10 +278,10 @@ class DoubaoServiceTest {
|
||||
.setApiKey(key).setModel("your Endpoint ID").build(), DoubaoService.class);
|
||||
final List<Message> messages = new ArrayList<>();
|
||||
messages.add(new Message("user","你怎么看待意大利面拌水泥?"));
|
||||
String contextId = "your contextId";
|
||||
final String contextId = "your contextId";
|
||||
|
||||
// 使用AtomicBoolean作为结束标志
|
||||
AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
doubaoService.chatContext(messages,contextId, data -> {
|
||||
assertNotNull(data);
|
||||
if (data.contains("[DONE]")) {
|
||||
|
||||
@ -49,9 +49,9 @@ class GrokServiceTest {
|
||||
@Test
|
||||
@Disabled
|
||||
void chatStream() {
|
||||
String prompt = "写一个疯狂星期四广告词";
|
||||
final String prompt = "写一个疯狂星期四广告词";
|
||||
// 使用AtomicBoolean作为结束标志
|
||||
AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
|
||||
grokService.chat(prompt, data -> {
|
||||
assertNotNull(data);
|
||||
@ -89,10 +89,10 @@ class GrokServiceTest {
|
||||
@Test
|
||||
@Disabled
|
||||
void messageStream() {
|
||||
String prompt = "给我一个KFC的广告词";
|
||||
final String prompt = "给我一个KFC的广告词";
|
||||
|
||||
// 使用AtomicBoolean作为结束标志
|
||||
AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
grokService.message(prompt, 4096, data -> {
|
||||
assertNotNull(data);
|
||||
if (data.contains("[DONE]")) {
|
||||
@ -122,11 +122,11 @@ class GrokServiceTest {
|
||||
@Disabled
|
||||
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);
|
||||
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 String prompt = "图片上有些什么?";
|
||||
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 isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
grokService.chatVision(prompt,images, data -> {
|
||||
assertNotNull(data);
|
||||
if (data.contains("[DONE]")) {
|
||||
|
||||
@ -52,9 +52,9 @@ class HutoolServiceTest {
|
||||
@Test
|
||||
@Disabled
|
||||
void chatStream() {
|
||||
String prompt = "写一个疯狂星期四广告词";
|
||||
final String prompt = "写一个疯狂星期四广告词";
|
||||
// 使用AtomicBoolean作为结束标志
|
||||
AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
|
||||
hutoolService.chat(prompt, data -> {
|
||||
assertNotNull(data);
|
||||
@ -94,11 +94,11 @@ class HutoolServiceTest {
|
||||
@Test
|
||||
@Disabled
|
||||
void testChatVisionStream() {
|
||||
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 String prompt = "图片上有些什么?";
|
||||
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 isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
hutoolService.chatVision(prompt,images, data -> {
|
||||
assertNotNull(data);
|
||||
if (data.contains("[DONE]")) {
|
||||
@ -160,7 +160,7 @@ class HutoolServiceTest {
|
||||
final String filePath = "your filePath";
|
||||
FileUtil.writeFromStream(inputStream, new File(filePath));
|
||||
|
||||
} catch (Exception e) {
|
||||
} catch (final Exception e) {
|
||||
throw new AIException("TTS测试失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
@ -56,9 +56,9 @@ class OpenaiServiceTest {
|
||||
@Test
|
||||
@Disabled
|
||||
void chatStream() {
|
||||
String prompt = "写一个疯狂星期四广告词";
|
||||
final String prompt = "写一个疯狂星期四广告词";
|
||||
// 使用AtomicBoolean作为结束标志
|
||||
AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
|
||||
openaiService.chat(prompt, data -> {
|
||||
assertNotNull(data);
|
||||
@ -91,11 +91,11 @@ class OpenaiServiceTest {
|
||||
void testChatVisionStream() {
|
||||
final OpenaiService openaiService = AIServiceFactory.getAIService(new AIConfigBuilder(ModelName.OPENAI.getValue())
|
||||
.setApiKey(key).setModel(Models.Openai.GPT_4O_MINI.getModel()).build(), OpenaiService.class);
|
||||
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 String prompt = "图片上有些什么?";
|
||||
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 isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
openaiService.chatVision(prompt,images, data -> {
|
||||
assertNotNull(data);
|
||||
if (data.contains("[DONE]")) {
|
||||
@ -226,7 +226,7 @@ class OpenaiServiceTest {
|
||||
messages.add(new Message("user","给我一个KFC疯狂星期四的文案"));
|
||||
|
||||
// 使用AtomicBoolean作为结束标志
|
||||
AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
final AtomicBoolean isDone = new AtomicBoolean(false);
|
||||
openaiService.chatReasoning(messages,OpenaiCommon.OpenaiReasoning.HIGH.getEffort(), data -> {
|
||||
assertNotNull(data);
|
||||
if (data.contains("[DONE]")) {
|
||||
|
||||
@ -201,7 +201,7 @@ public class BeanUtil {
|
||||
}
|
||||
|
||||
// 先尝试直接获取属性
|
||||
if (bean instanceof Map<?, ?> map) {
|
||||
if (bean instanceof final Map<?, ?> map) {
|
||||
if (map.containsKey(expression)) {
|
||||
return (T) map.get(expression);
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ public class Number128 extends Number implements Comparable<Number128>{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o instanceof Number128 number128) {
|
||||
if (o instanceof final Number128 number128) {
|
||||
return leastSigBits == number128.leastSigBits && mostSigBits == number128.mostSigBits;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -1408,7 +1408,7 @@ public class CollUtil {
|
||||
* @return 合并后的新列表
|
||||
* @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)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ public class SetUtil {
|
||||
if (null == iterable) {
|
||||
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 of(isLinked, iterable.iterator());
|
||||
|
||||
@ -182,14 +182,14 @@ public class ArrayConverter extends AbstractConverter implements MatcherConverte
|
||||
*/
|
||||
private Object convertIterableToArray(final Class<?> targetComponentType, final Iterable<?> value) {
|
||||
final Object result;
|
||||
if (value instanceof List<?> list) {
|
||||
if (value instanceof final List<?> list) {
|
||||
// List转数组
|
||||
final int size = list.size();
|
||||
result = Array.newInstance(targetComponentType, size);
|
||||
for (int i = 0; i < size; 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());
|
||||
|
||||
|
||||
@ -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)
|
||||
throws ConvertException {
|
||||
Map map = null;
|
||||
if (value instanceof Map.Entry entry) {
|
||||
if (value instanceof final Map.Entry entry) {
|
||||
map = MapUtil.of(entry.getKey(), entry.getValue());
|
||||
} else if (value instanceof Pair) {
|
||||
final Pair entry = (Pair<?, ?>) value;
|
||||
map = MapUtil.of(entry.getLeft(), entry.getRight());
|
||||
} else if (value instanceof Map) {
|
||||
map = (Map) value;
|
||||
} else if (value instanceof CharSequence str) {
|
||||
} else if (value instanceof final CharSequence str) {
|
||||
map = strToMap(str);
|
||||
} else if (BeanUtil.isWritableBean(value.getClass())) {
|
||||
// 一次性只读场景,包装为Map效率更高
|
||||
|
||||
@ -80,14 +80,14 @@ public class PairConverter extends ConverterWithRoot implements Serializable {
|
||||
public Pair<?, ?> convert(final Type leftType, final Type rightType, final Object value)
|
||||
throws ConvertException {
|
||||
Map map = null;
|
||||
if (value instanceof Map.Entry entry) {
|
||||
if (value instanceof final Map.Entry entry) {
|
||||
map = MapUtil.of(entry.getKey(), entry.getValue());
|
||||
} else if (value instanceof Pair) {
|
||||
final Pair entry = (Pair<?, ?>) value;
|
||||
map = MapUtil.of(entry.getLeft(), entry.getRight());
|
||||
} else if (value instanceof Map) {
|
||||
map = (Map) value;
|
||||
} else if (value instanceof CharSequence str) {
|
||||
} else if (value instanceof final CharSequence str) {
|
||||
map = strToMap(str);
|
||||
} else if (BeanUtil.isReadableBean(value.getClass())) {
|
||||
// 一次性只读场景,包装为Map效率更高
|
||||
|
||||
@ -36,7 +36,7 @@ public class StackTraceElementConverter extends AbstractConverter {
|
||||
|
||||
@Override
|
||||
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 methodName = MapUtil.getStr(map, "methodName");
|
||||
|
||||
@ -110,7 +110,7 @@ public class TemporalAccessorConverter extends AbstractConverter {
|
||||
} else if (value instanceof Date) {
|
||||
final DateTime dateTime = DateUtil.date((Date) value);
|
||||
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());
|
||||
} else {
|
||||
return parseFromCharSequence(targetClass, convertToStr(value));
|
||||
|
||||
@ -87,7 +87,7 @@ public class XMLGregorianCalendarConverter extends AbstractConverter {
|
||||
// Handle Date
|
||||
if (value instanceof Date) {
|
||||
gregorianCalendar.setTime((Date) value);
|
||||
} else if (value instanceof Calendar calendar) {
|
||||
} else if (value instanceof final Calendar calendar) {
|
||||
gregorianCalendar.setTimeZone(calendar.getTimeZone());
|
||||
gregorianCalendar.setFirstDayOfWeek(calendar.getFirstDayOfWeek());
|
||||
gregorianCalendar.setLenient(calendar.isLenient());
|
||||
|
||||
@ -348,18 +348,7 @@ public class DatePattern {
|
||||
* Inner class to output a constant single character.
|
||||
* </p>
|
||||
*/
|
||||
private static class CharacterLiteral 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;
|
||||
}
|
||||
|
||||
private record CharacterLiteral(char mValue) implements Rule {
|
||||
@Override
|
||||
public int estimateLength() {
|
||||
return 1;
|
||||
@ -376,18 +365,7 @@ public class DatePattern {
|
||||
* Inner class to output a constant string.
|
||||
* </p>
|
||||
*/
|
||||
private static class StringLiteral 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;
|
||||
}
|
||||
|
||||
private record StringLiteral(String mValue) implements Rule {
|
||||
@Override
|
||||
public int estimateLength() {
|
||||
return mValue.length();
|
||||
@ -404,21 +382,7 @@ public class DatePattern {
|
||||
* Inner class to output one of a set of values.
|
||||
* </p>
|
||||
*/
|
||||
private static class TextField 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;
|
||||
}
|
||||
|
||||
private record TextField(int mField, String[] mValues) implements Rule {
|
||||
@Override
|
||||
public int estimateLength() {
|
||||
int max = 0;
|
||||
@ -431,6 +395,7 @@ public class DatePattern {
|
||||
return max;
|
||||
}
|
||||
|
||||
@SuppressWarnings("MagicConstant")
|
||||
@Override
|
||||
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
|
||||
buffer.append(mValues[calendar.get(mField)]);
|
||||
@ -442,23 +407,14 @@ public class DatePattern {
|
||||
* Inner class to output an unpadded number.
|
||||
* </p>
|
||||
*/
|
||||
private static class UnpaddedNumberField 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;
|
||||
}
|
||||
private record UnpaddedNumberField(int mField) implements NumberRule {
|
||||
|
||||
@Override
|
||||
public int estimateLength() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@SuppressWarnings("MagicConstant")
|
||||
@Override
|
||||
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
|
||||
appendTo(buffer, calendar.get(mField));
|
||||
@ -515,23 +471,18 @@ public class DatePattern {
|
||||
* Inner class to output a padded number.
|
||||
* </p>
|
||||
*/
|
||||
private static class PaddedNumberField implements NumberRule {
|
||||
private final int mField;
|
||||
private final int mSize;
|
||||
|
||||
private record PaddedNumberField(int mField, int mSize) implements NumberRule {
|
||||
/**
|
||||
* Constructs an instance of {@code PaddedNumberField}.
|
||||
*
|
||||
* @param field the field
|
||||
* @param size size of the output field
|
||||
* @param mField the field
|
||||
* @param mSize size of the output field
|
||||
*/
|
||||
PaddedNumberField(final int field, final int size) {
|
||||
if (size < 3) {
|
||||
private PaddedNumberField {
|
||||
if (mSize < 3) {
|
||||
// Should use UnpaddedNumberField or TwoDigitNumberField.
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
mField = field;
|
||||
mSize = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -539,6 +490,7 @@ public class DatePattern {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
@SuppressWarnings("MagicConstant")
|
||||
@Override
|
||||
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
|
||||
appendTo(buffer, calendar.get(mField));
|
||||
@ -555,23 +507,13 @@ public class DatePattern {
|
||||
* Inner class to output a two digit number.
|
||||
* </p>
|
||||
*/
|
||||
private static class TwoDigitNumberField 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;
|
||||
}
|
||||
|
||||
private record TwoDigitNumberField(int mField) implements NumberRule {
|
||||
@Override
|
||||
public int estimateLength() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@SuppressWarnings("MagicConstant")
|
||||
@Override
|
||||
public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException {
|
||||
appendTo(buffer, calendar.get(mField));
|
||||
@ -652,18 +594,7 @@ public class DatePattern {
|
||||
* Inner class to output the twelve hour field.
|
||||
* </p>
|
||||
*/
|
||||
private static class TwelveHourField 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;
|
||||
}
|
||||
|
||||
private record TwelveHourField(NumberRule mRule) implements NumberRule {
|
||||
@Override
|
||||
public int estimateLength() {
|
||||
return mRule.estimateLength();
|
||||
@ -685,22 +616,9 @@ public class DatePattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Inner class to output the twenty four hour field.
|
||||
* </p>
|
||||
*/
|
||||
private static class TwentyFourHourField 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;
|
||||
}
|
||||
|
||||
private record TwentyFourHourField(NumberRule mRule) implements NumberRule {
|
||||
@Override
|
||||
public int estimateLength() {
|
||||
return mRule.estimateLength();
|
||||
@ -722,17 +640,9 @@ public class DatePattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Inner class to output the numeric day in week.
|
||||
* </p>
|
||||
*/
|
||||
private static class DayInWeekField implements NumberRule {
|
||||
private final NumberRule mRule;
|
||||
|
||||
DayInWeekField(final NumberRule rule) {
|
||||
mRule = rule;
|
||||
}
|
||||
|
||||
private record DayInWeekField(NumberRule mRule) implements NumberRule {
|
||||
@Override
|
||||
public int estimateLength() {
|
||||
return mRule.estimateLength();
|
||||
@ -751,17 +661,9 @@ public class DatePattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Inner class to output the numeric day in week.
|
||||
* </p>
|
||||
*/
|
||||
private static class WeekYear implements NumberRule {
|
||||
private final NumberRule mRule;
|
||||
|
||||
WeekYear(final NumberRule rule) {
|
||||
mRule = rule;
|
||||
}
|
||||
|
||||
private record WeekYear(NumberRule mRule) implements NumberRule {
|
||||
@Override
|
||||
public int estimateLength() {
|
||||
return mRule.estimateLength();
|
||||
@ -784,9 +686,7 @@ public class DatePattern {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Inner class to output a time zone name.
|
||||
* </p>
|
||||
*/
|
||||
private static class TimeZoneNameRule implements Rule {
|
||||
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}.
|
||||
* </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_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
|
||||
public int estimateLength() {
|
||||
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}.
|
||||
* </p>
|
||||
*/
|
||||
private static class Iso8601_Rule implements Rule {
|
||||
private record Iso8601_Rule(int length) implements Rule {
|
||||
|
||||
// Sign TwoDigitHours or Z
|
||||
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.
|
||||
*
|
||||
* @param length The number of characters in output (unless Z is output)
|
||||
*/
|
||||
Iso8601_Rule(final int length) {
|
||||
this.length = length;
|
||||
private Iso8601_Rule {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1103,7 +987,7 @@ public class DatePattern {
|
||||
if (this == obj) {
|
||||
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 false;
|
||||
|
||||
@ -436,7 +436,7 @@ public class FastDateFormat extends Format implements PositionDateParser, DatePr
|
||||
// -----------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (!(obj instanceof FastDateFormat other)) {
|
||||
if (!(obj instanceof final FastDateFormat other)) {
|
||||
return false;
|
||||
}
|
||||
// no need to check parser, as it has same invariants as printer
|
||||
|
||||
@ -75,7 +75,7 @@ public class SimpleDateBasic implements DateBasic, Serializable {
|
||||
// ----------------------------------------------------------------------- Basics
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (!(obj instanceof FastDatePrinter other)) {
|
||||
if (!(obj instanceof final FastDatePrinter other)) {
|
||||
return false;
|
||||
}
|
||||
return pattern.equals(other.pattern) && timeZone.equals(other.timeZone) && locale.equals(other.locale);
|
||||
|
||||
@ -55,7 +55,7 @@ public class ManifestUtil {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
|
||||
if (connection instanceof JarURLConnection conn) {
|
||||
if (connection instanceof final JarURLConnection conn) {
|
||||
return getManifest(conn);
|
||||
}
|
||||
return null;
|
||||
|
||||
@ -89,7 +89,7 @@ public class JarResource extends UrlResource {
|
||||
*/
|
||||
private JarFile doGetJarFile() throws IOException {
|
||||
final URLConnection con = getUrl().openConnection();
|
||||
if (con instanceof JarURLConnection jarCon) {
|
||||
if (con instanceof final JarURLConnection jarCon) {
|
||||
return jarCon.getJarFile();
|
||||
} else {
|
||||
final String urlFile = getUrl().getFile();
|
||||
|
||||
@ -127,7 +127,7 @@ public class ResourceFinder {
|
||||
String rootEntryPath;
|
||||
final boolean closeJarFile;
|
||||
|
||||
if (conn instanceof JarURLConnection jarCon) {
|
||||
if (conn instanceof final JarURLConnection jarCon) {
|
||||
UrlUtil.useCachesIfNecessary(jarCon);
|
||||
jarFile = jarCon.getJarFile();
|
||||
final JarEntry jarEntry = jarCon.getJarEntry();
|
||||
|
||||
@ -52,7 +52,7 @@ public class Console {
|
||||
* @param obj 要打印的对象
|
||||
*/
|
||||
public static void log(final Object obj) {
|
||||
if (obj instanceof Throwable e) {
|
||||
if (obj instanceof final Throwable e) {
|
||||
log(e, e.getMessage());
|
||||
} else {
|
||||
log(TEMPLATE_VAR, obj);
|
||||
@ -219,7 +219,7 @@ public class Console {
|
||||
* @param obj 要打印的对象
|
||||
*/
|
||||
public static void error(final Object obj) {
|
||||
if (obj instanceof Throwable e) {
|
||||
if (obj instanceof final Throwable e) {
|
||||
error(e, e.getMessage());
|
||||
} else {
|
||||
error(TEMPLATE_VAR, obj);
|
||||
|
||||
@ -541,7 +541,7 @@ public class Opt<T> {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof Opt<?> other)) {
|
||||
if (!(obj instanceof final Opt<?> other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ public class Triple<L, M, R> extends Pair<L, R> {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o instanceof Triple<?, ?, ?> triple) {
|
||||
if (o instanceof final Triple<?, ?, ?> triple) {
|
||||
return Objects.equals(getLeft(), triple.getLeft()) &&
|
||||
Objects.equals(getMiddle(), triple.getMiddle()) &&
|
||||
Objects.equals(getRight(), triple.getRight());
|
||||
|
||||
@ -39,7 +39,7 @@ public abstract class AbsEntry<K, V> implements Map.Entry<K, V> {
|
||||
|
||||
@Override
|
||||
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())
|
||||
&& ObjUtil.equals(this.getValue(), that.getValue());
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ public abstract class AbsTable<R, C, V> implements Table<R, C, V> {
|
||||
public boolean equals(final Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
} else if (obj instanceof Table<?, ?, ?> that) {
|
||||
} else if (obj instanceof final Table<?, ?, ?> that) {
|
||||
return this.cellSet().equals(that.cellSet());
|
||||
} else {
|
||||
return false;
|
||||
@ -231,7 +231,7 @@ public abstract class AbsTable<R, C, V> implements Table<R, C, V> {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Cell<?, ?, ?> other) {
|
||||
if (obj instanceof final Cell<?, ?, ?> other) {
|
||||
return ObjUtil.equals(rowKey, other.getRowKey())
|
||||
&& ObjUtil.equals(columnKey, other.getColumnKey())
|
||||
&& ObjUtil.equals(value, other.getValue());
|
||||
|
||||
@ -161,7 +161,7 @@ public class ChineseNumberFormatter {
|
||||
public String format(final BigDecimal amount) {
|
||||
final long longValue = amount.longValue();
|
||||
|
||||
String formatAmount;
|
||||
final String formatAmount;
|
||||
if (amount.scale() <= 0) {
|
||||
formatAmount = format(longValue);
|
||||
} else {
|
||||
|
||||
@ -618,7 +618,7 @@ public final class Fraction extends Number implements Comparable<Fraction> {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof Fraction other)) {
|
||||
if (!(obj instanceof final Fraction other)) {
|
||||
return false;
|
||||
}
|
||||
return getNumerator() == other.getNumerator() && getDenominator() == other.getDenominator();
|
||||
|
||||
@ -662,7 +662,7 @@ public class UrlUtil {
|
||||
try {
|
||||
conn = url.openConnection();
|
||||
useCachesIfNecessary(conn);
|
||||
if (conn instanceof HttpURLConnection httpCon) {
|
||||
if (conn instanceof final HttpURLConnection httpCon) {
|
||||
httpCon.setRequestMethod("HEAD");
|
||||
}
|
||||
return conn.getContentLengthLong();
|
||||
|
||||
@ -60,7 +60,7 @@ public class MethodTypeUtil {
|
||||
if (null == declaringClass) {
|
||||
declaringClass = executable.getDeclaringClass();
|
||||
}
|
||||
if (executable instanceof Method method) {
|
||||
if (executable instanceof final Method method) {
|
||||
return MethodType.methodType(method.getReturnType(), declaringClass, method.getParameterTypes());
|
||||
} else {
|
||||
final Constructor<?> constructor = (Constructor<?>) executable;
|
||||
|
||||
@ -57,7 +57,7 @@ public class JdkServiceLoaderUtil {
|
||||
break;
|
||||
}
|
||||
instance = iterator.next();
|
||||
} catch (ServiceConfigurationError | NoClassDefFoundError e) {
|
||||
} catch (final ServiceConfigurationError | NoClassDefFoundError e) {
|
||||
// 安全忽略当前实现,尝试下一个
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2416,8 +2416,25 @@ public class CharSequenceUtil extends StrValidator {
|
||||
if (null == str1 || null == str2) {
|
||||
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
|
||||
|
||||
@ -3954,7 +3971,7 @@ public class CharSequenceUtil extends StrValidator {
|
||||
* @return StringBuilder对象
|
||||
* @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();
|
||||
for (final CharSequence str : strs) {
|
||||
sb.append(strEditor.apply( str));
|
||||
|
||||
@ -236,7 +236,7 @@ public class StrJoiner implements Appendable, Serializable {
|
||||
append((Iterator<?>) obj);
|
||||
} else if (obj instanceof Iterable) {
|
||||
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());
|
||||
} else {
|
||||
append(ConvertUtil.toStr(obj));
|
||||
@ -448,7 +448,7 @@ public class StrJoiner implements Appendable, Serializable {
|
||||
* @param appendable {@link 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)) {
|
||||
this.hasContent = true;
|
||||
}
|
||||
|
||||
@ -17,9 +17,12 @@
|
||||
package cn.hutool.v7.core.text.finder;
|
||||
|
||||
import cn.hutool.v7.core.lang.Assert;
|
||||
import cn.hutool.v7.core.text.CharSequenceUtil;
|
||||
|
||||
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 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) {
|
||||
Assert.notNull(this.text, "Text to find must be not null!");
|
||||
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) {
|
||||
from = 0;
|
||||
}
|
||||
int endLimit = getValidEndIndex();
|
||||
if (negative) {
|
||||
for (int i = from; i > endLimit; i--) {
|
||||
if (CharSequenceUtil.isSubEquals(text, i, strToFind, 0, subLen, caseInsensitive)) {
|
||||
final int endLimit = textLen - subLen;
|
||||
int i = from;
|
||||
while (i <= endLimit) {
|
||||
if (isSubEquals(text, i, strToFind, 0, subLen, caseInsensitive)) {
|
||||
return i;
|
||||
}
|
||||
if (i + subLen >= textLen) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
endLimit = endLimit - subLen + 1;
|
||||
for (int i = from; i < endLimit; i++) {
|
||||
if (CharSequenceUtil.isSubEquals(text, i, strToFind, 0, subLen, caseInsensitive)) {
|
||||
return i;
|
||||
}
|
||||
final char nextChar = text.charAt(i + subLen);
|
||||
final int jump = forwardOffsetMap.getOrDefault(
|
||||
caseInsensitive ? Character.toLowerCase(nextChar) : nextChar,
|
||||
subLen + 1
|
||||
);
|
||||
i += jump;
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,4 +128,44 @@ public class StrFinder extends TextFinder {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,9 +795,9 @@ public class ThreadUtil {
|
||||
* @since 4.5.8
|
||||
*/
|
||||
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);
|
||||
} catch (IOException e) {
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1022,20 +1022,20 @@ public class BeanUtilTest {
|
||||
|
||||
@Test
|
||||
void checkBean_withNullBean_shouldReturnTrue() {
|
||||
Predicate<Field> predicate = field -> true;
|
||||
final Predicate<Field> predicate = field -> true;
|
||||
assertTrue(BeanUtil.checkBean(null, predicate));
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkBean_withNoMatchingFields_shouldReturnFalse() {
|
||||
Person bean = new Person();
|
||||
Predicate<Field> predicate = field -> false;
|
||||
final Person bean = new Person();
|
||||
final Predicate<Field> predicate = field -> false;
|
||||
assertFalse(BeanUtil.checkBean(bean, predicate));
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkBean_withMatchingField_shouldReturnTrue() {
|
||||
Person bean = new Person();
|
||||
final Person bean = new Person();
|
||||
Predicate<Field> predicate = field -> "name".equals(field.getName());
|
||||
assertTrue(BeanUtil.checkBean(bean, predicate));
|
||||
|
||||
@ -1046,12 +1046,12 @@ public class BeanUtilTest {
|
||||
@Test
|
||||
void findEditor_shouldReturnEditorForRegisteredType() {
|
||||
// Given
|
||||
Class<?> type = Integer.class;
|
||||
final Class<?> type = Integer.class;
|
||||
// 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
|
||||
PropertyEditor actualEditor = BeanUtil.findEditor(type);
|
||||
final PropertyEditor actualEditor = BeanUtil.findEditor(type);
|
||||
|
||||
// Then
|
||||
assertNotNull(actualEditor);
|
||||
@ -1062,10 +1062,10 @@ public class BeanUtilTest {
|
||||
void findEditor_shouldReturnNullForUnregisteredType() {
|
||||
// Given
|
||||
class CustomUnregisteredType {}
|
||||
Class<?> type = CustomUnregisteredType.class;
|
||||
final Class<?> type = CustomUnregisteredType.class;
|
||||
|
||||
// When
|
||||
PropertyEditor editor = BeanUtil.findEditor(type);
|
||||
final PropertyEditor editor = BeanUtil.findEditor(type);
|
||||
|
||||
// Then
|
||||
assertNull(editor);
|
||||
@ -1074,10 +1074,10 @@ public class BeanUtilTest {
|
||||
@Test
|
||||
void findEditor_shouldHandlePrimitiveTypes() {
|
||||
// Given
|
||||
Class<?> type = int.class;
|
||||
final Class<?> type = int.class;
|
||||
|
||||
// When
|
||||
PropertyEditor editor = BeanUtil.findEditor(type);
|
||||
final PropertyEditor editor = BeanUtil.findEditor(type);
|
||||
|
||||
// Then
|
||||
assertNotNull(editor);
|
||||
@ -1085,7 +1085,7 @@ public class BeanUtilTest {
|
||||
|
||||
@Test
|
||||
void descForEach_shouldProcessAllProperties() {
|
||||
List<String> processedProperties = new ArrayList<>();
|
||||
final List<String> processedProperties = new ArrayList<>();
|
||||
|
||||
// 执行
|
||||
BeanUtil.descForEach(Person.class, propDesc -> processedProperties.add(propDesc.getFieldName()));
|
||||
@ -1099,7 +1099,7 @@ public class BeanUtilTest {
|
||||
|
||||
@Test
|
||||
public void testIsMatchName_SimpleMatch() {
|
||||
String testObj = "test";
|
||||
final String testObj = "test";
|
||||
assertTrue(BeanUtil.isMatchName(testObj, "String", true));
|
||||
assertTrue(BeanUtil.isMatchName(testObj, "string", true));
|
||||
|
||||
@ -1110,7 +1110,7 @@ public class BeanUtilTest {
|
||||
|
||||
@Test
|
||||
public void testIsMatchName_FullMatch() {
|
||||
Integer testObj = 123;
|
||||
final Integer testObj = 123;
|
||||
assertTrue(BeanUtil.isMatchName(testObj, "java.lang.Integer", false));
|
||||
assertFalse(BeanUtil.isMatchName(testObj, "Integer", false));
|
||||
|
||||
@ -1120,7 +1120,7 @@ public class BeanUtilTest {
|
||||
|
||||
@Test
|
||||
void testGetPropertyDescriptor_ExistingField() {
|
||||
PropertyDescriptor pd = BeanUtil.getPropertyDescriptor(Person.class, "name");
|
||||
final PropertyDescriptor pd = BeanUtil.getPropertyDescriptor(Person.class, "name");
|
||||
assertNotNull(pd);
|
||||
assertEquals("name", pd.getName());
|
||||
assertEquals(String.class, pd.getPropertyType());
|
||||
@ -1134,7 +1134,7 @@ public class BeanUtilTest {
|
||||
|
||||
@Test
|
||||
void testBeanToMap_IgnoreNullValue() {
|
||||
Person person = new Person();
|
||||
final Person person = new Person();
|
||||
person.setName(null);
|
||||
person.setAge(25);
|
||||
|
||||
|
||||
@ -36,8 +36,8 @@ public class DynaBeanTest {
|
||||
|
||||
@Test
|
||||
void createDynaBean_withPlainObject_shouldReturnDynaBean() {
|
||||
BeanUtilTest.Person bean = new BeanUtilTest.Person();
|
||||
DynaBean dynaBean = BeanUtil.createDynaBean(bean);
|
||||
final BeanUtilTest.Person bean = new BeanUtilTest.Person();
|
||||
final DynaBean dynaBean = BeanUtil.createDynaBean(bean);
|
||||
|
||||
assertNotNull(dynaBean);
|
||||
assertEquals(bean, dynaBean.getBean());
|
||||
|
||||
@ -102,7 +102,7 @@ public class SimpleCacheTest {
|
||||
cache.get("key5", ()->"value5");
|
||||
|
||||
String key = null;
|
||||
for (Map.Entry<String, String> entry : cache) {
|
||||
for (final Map.Entry<String, String> entry : cache) {
|
||||
if ("value3".equals(entry.getValue())) {
|
||||
key = entry.getKey();
|
||||
break;
|
||||
|
||||
@ -996,25 +996,25 @@ public class CollUtilTest {
|
||||
@Test
|
||||
public void zipTest2() {
|
||||
// 1. 正常情况测试
|
||||
List<String> list1 = ListUtil.of("a", "b", "c");
|
||||
List<Integer> list2 = ListUtil.of(1, 2, 3);
|
||||
List<String> result = CollUtil.zip(list1, list2, (s, i) -> s + i);
|
||||
final List<String> list1 = ListUtil.of("a", "b", "c");
|
||||
final List<Integer> list2 = ListUtil.of(1, 2, 3);
|
||||
final List<String> result = CollUtil.zip(list1, list2, (s, i) -> s + i);
|
||||
assertEquals(ListUtil.of("a1", "b2", "c3"), result);
|
||||
|
||||
// 2. 空集合测试
|
||||
List<String> emptyList = ListUtil.of();
|
||||
List<String> emptyResult = CollUtil.zip(emptyList, list2, (s, i) -> s + i);
|
||||
final List<String> emptyList = ListUtil.of();
|
||||
final List<String> emptyResult = CollUtil.zip(emptyList, list2, (s, i) -> s + i);
|
||||
assertTrue(emptyResult.isEmpty());
|
||||
|
||||
// 3. 不同大小集合测试(以较小集合为准)
|
||||
List<Integer> longerList = ListUtil.of(1, 2, 3, 4, 5);
|
||||
List<String> sizedResult = CollUtil.zip(list1, longerList, (s, i) -> s + i);
|
||||
final List<Integer> longerList = ListUtil.of(1, 2, 3, 4, 5);
|
||||
final List<String> sizedResult = CollUtil.zip(list1, longerList, (s, i) -> s + i);
|
||||
assertEquals(3, sizedResult.size());
|
||||
assertEquals("a1", sizedResult.get(0));
|
||||
|
||||
// 4. 自定义zipper函数测试
|
||||
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<Double> list3 = ListUtil.of(1.1, 2.2, 3.3);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1166,11 +1166,11 @@ public class CollUtilTest {
|
||||
|
||||
@Test
|
||||
void getFirstTestWithPredicateTest(){
|
||||
Animal dog = new Animal("dog", 2);
|
||||
Animal cat = new Animal("cat", 3);
|
||||
Animal bear = new Animal("bear", 4);
|
||||
final Animal dog = new Animal("dog", 2);
|
||||
final Animal cat = new Animal("cat", 3);
|
||||
final Animal bear = new Animal("bear", 4);
|
||||
|
||||
List<Animal> list = new ArrayList<>();
|
||||
final List<Animal> list = new ArrayList<>();
|
||||
list.add(dog);
|
||||
list.add(cat);
|
||||
list.add(bear);
|
||||
|
||||
@ -31,8 +31,8 @@ public class CopiedIterTest {
|
||||
|
||||
@Test
|
||||
public void copyOf() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
Iterator<Integer> iter = list.iterator();
|
||||
final List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
final Iterator<Integer> iter = list.iterator();
|
||||
Assertions.assertEquals((Integer)1, iter.next());
|
||||
|
||||
Assertions.assertEquals((Integer)2, CopiedIter.copyOf(iter).next());
|
||||
@ -46,8 +46,8 @@ public class CopiedIterTest {
|
||||
|
||||
@Test
|
||||
public void next() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
Iterator<Integer> iter = CopiedIter.copyOf(list.iterator());
|
||||
final List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
final Iterator<Integer> iter = CopiedIter.copyOf(list.iterator());
|
||||
Assertions.assertEquals((Integer)1, iter.next());
|
||||
Assertions.assertEquals((Integer)2, iter.next());
|
||||
Assertions.assertEquals((Integer)3, iter.next());
|
||||
@ -55,8 +55,8 @@ public class CopiedIterTest {
|
||||
|
||||
@Test
|
||||
public void remove() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
Iterator<Integer> iter = CopiedIter.copyOf(list.iterator());
|
||||
final List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
final Iterator<Integer> iter = CopiedIter.copyOf(list.iterator());
|
||||
Assertions.assertThrows(UnsupportedOperationException.class, iter::remove);
|
||||
}
|
||||
|
||||
|
||||
@ -30,16 +30,16 @@ public class EnumerationIterTest {
|
||||
|
||||
@Test
|
||||
public void testHasNext() {
|
||||
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
final Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
final EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
Assertions.assertTrue(iter.hasNext());
|
||||
Assertions.assertFalse(new EnumerationIter<>(new IteratorEnumeration<>(Collections.emptyIterator())).hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNext() {
|
||||
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
final Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
final EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
Assertions.assertEquals((Integer)1, iter.next());
|
||||
Assertions.assertEquals((Integer)2, iter.next());
|
||||
Assertions.assertEquals((Integer)3, iter.next());
|
||||
@ -47,15 +47,15 @@ public class EnumerationIterTest {
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
final Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
final EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
Assertions.assertThrows(UnsupportedOperationException.class, iter::remove);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator() {
|
||||
Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
final Enumeration<Integer> enumeration = new IteratorEnumeration<>(Arrays.asList(1, 2, 3).iterator());
|
||||
final EnumerationIter<Integer> iter = new EnumerationIter<>(enumeration);
|
||||
Assertions.assertSame(iter, iter.iterator());
|
||||
}
|
||||
|
||||
|
||||
@ -51,27 +51,27 @@ public class FilterIterTest {
|
||||
@Test
|
||||
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)3, iter.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
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);
|
||||
}
|
||||
|
||||
@Test
|
||||
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());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFilter() {
|
||||
Predicate<Integer> predicate = i -> true;
|
||||
FilterIter<Integer> iter = new FilterIter<>(Collections.emptyIterator(), predicate);
|
||||
final Predicate<Integer> predicate = i -> true;
|
||||
final FilterIter<Integer> iter = new FilterIter<>(Collections.emptyIterator(), predicate);
|
||||
Assertions.assertSame(predicate, iter.getFilter());
|
||||
}
|
||||
|
||||
|
||||
@ -30,16 +30,16 @@ public class IteratorEnumerationTest {
|
||||
|
||||
@Test
|
||||
public void testHasMoreElements() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
IteratorEnumeration<Integer> enumeration = new IteratorEnumeration<>(list.iterator());
|
||||
final List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
final IteratorEnumeration<Integer> enumeration = new IteratorEnumeration<>(list.iterator());
|
||||
Assertions.assertTrue(enumeration.hasMoreElements());
|
||||
Assertions.assertFalse(new IteratorEnumeration<>(Collections.emptyIterator()).hasMoreElements());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextElement() {
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
IteratorEnumeration<Integer> enumeration = new IteratorEnumeration<>(list.iterator());
|
||||
final List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
final IteratorEnumeration<Integer> enumeration = new IteratorEnumeration<>(list.iterator());
|
||||
Assertions.assertEquals((Integer)1, enumeration.nextElement());
|
||||
Assertions.assertEquals((Integer)2, enumeration.nextElement());
|
||||
Assertions.assertEquals((Integer)3, enumeration.nextElement());
|
||||
|
||||
@ -30,16 +30,16 @@ public class PartitionIterTest {
|
||||
|
||||
@Test
|
||||
public void testHasNext() {
|
||||
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator();
|
||||
PartitionIter<Integer> partitionIter = new PartitionIter<>(iter, 2);
|
||||
final Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator();
|
||||
final PartitionIter<Integer> partitionIter = new PartitionIter<>(iter, 2);
|
||||
Assertions.assertTrue(partitionIter.hasNext());
|
||||
Assertions.assertFalse(new PartitionIter<>(Collections.emptyIterator(), 1).hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNext() {
|
||||
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator();
|
||||
PartitionIter<Integer> partitionIter = new PartitionIter<>(iter, 2);
|
||||
final Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4).iterator();
|
||||
final PartitionIter<Integer> partitionIter = new PartitionIter<>(iter, 2);
|
||||
Assertions.assertEquals(Arrays.asList(1, 2), partitionIter.next());
|
||||
Assertions.assertEquals(Arrays.asList(3, 4), partitionIter.next());
|
||||
}
|
||||
|
||||
@ -32,14 +32,14 @@ public class TransIterTest {
|
||||
|
||||
@Test
|
||||
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.assertFalse(new TransIter<>(Collections.emptyIterator(), Function.identity()).hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
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("2", iter.next());
|
||||
Assertions.assertEquals("3", iter.next());
|
||||
@ -47,8 +47,8 @@ public class TransIterTest {
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
List<Integer> list = ListUtil.of(1, 2, 3);
|
||||
TransIter<Integer, String> iter = new TransIter<>(list.iterator(), String::valueOf);
|
||||
final List<Integer> list = ListUtil.of(1, 2, 3);
|
||||
final TransIter<Integer, String> iter = new TransIter<>(list.iterator(), String::valueOf);
|
||||
iter.next();
|
||||
iter.remove();
|
||||
iter.next();
|
||||
|
||||
@ -39,8 +39,8 @@ public class ShiChenTest {
|
||||
assertEquals(1, ShiChen.toModernTime("子正").between(DateUnit.HOUR));
|
||||
|
||||
// 测试所有时辰
|
||||
String[] times = {"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
|
||||
for (String time : times) {
|
||||
final String[] times = {"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
|
||||
for (final String time : times) {
|
||||
assertEquals(2, ShiChen.toModernTime(time + "时").between(DateUnit.HOUR));
|
||||
assertEquals(1, ShiChen.toModernTime(time + "初").between(DateUnit.HOUR));
|
||||
assertEquals(1, ShiChen.toModernTime(time + "正").between(DateUnit.HOUR));
|
||||
|
||||
@ -41,7 +41,7 @@ public class PredicateUtilTest {
|
||||
|
||||
@Test
|
||||
public void andTest() {
|
||||
boolean condition = Stream.of(1, 3, 5)
|
||||
final boolean condition = Stream.of(1, 3, 5)
|
||||
.allMatch(
|
||||
PredicateUtil.and(
|
||||
Objects::nonNull,
|
||||
@ -54,7 +54,7 @@ public class PredicateUtilTest {
|
||||
|
||||
@Test
|
||||
public void orTest() {
|
||||
boolean condition = Stream.of(1, 3, 5)
|
||||
final boolean condition = Stream.of(1, 3, 5)
|
||||
.anyMatch(
|
||||
PredicateUtil.or(
|
||||
Objects::isNull,
|
||||
|
||||
@ -50,7 +50,7 @@ public class MutableBoolTest extends BaseMutableTest<Boolean, MutableBool> {
|
||||
* @return 值
|
||||
*/
|
||||
@Override
|
||||
MutableBool getMutable(Boolean value) {
|
||||
MutableBool getMutable(final Boolean value) {
|
||||
return new MutableBool(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ public class MutableByteTest extends BaseMutableTest<Number, MutableByte> {
|
||||
* @return 值
|
||||
*/
|
||||
@Override
|
||||
MutableByte getMutable(Number value) {
|
||||
MutableByte getMutable(final Number value) {
|
||||
return new MutableByte(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ public class MutableDoubleTest extends BaseMutableTest<Number, MutableDouble> {
|
||||
* @return 值
|
||||
*/
|
||||
@Override
|
||||
MutableDouble getMutable(Number value) {
|
||||
MutableDouble getMutable(final Number value) {
|
||||
return new MutableDouble(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ public class MutableEntryTest extends BaseMutableTest<Map.Entry<String, String>,
|
||||
* @return 值
|
||||
*/
|
||||
@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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ public class MutableFloatTest extends BaseMutableTest<Number, MutableFloat> {
|
||||
* @return 值
|
||||
*/
|
||||
@Override
|
||||
MutableFloat getMutable(Number value) {
|
||||
MutableFloat getMutable(final Number value) {
|
||||
return new MutableFloat(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ public class MutableIntTest extends BaseMutableTest<Number, MutableInt> {
|
||||
* @return 值
|
||||
*/
|
||||
@Override
|
||||
MutableInt getMutable(Number value) {
|
||||
MutableInt getMutable(final Number value) {
|
||||
return new MutableInt(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ public class MutableLongTest extends BaseMutableTest<Number, MutableLong> {
|
||||
* @return 值
|
||||
*/
|
||||
@Override
|
||||
MutableLong getMutable(Number value) {
|
||||
MutableLong getMutable(final Number value) {
|
||||
return new MutableLong(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ class MutableObjTest extends BaseMutableTest<String, MutableObj<String>> {
|
||||
* @return 值
|
||||
*/
|
||||
@Override
|
||||
MutableObj<String> getMutable(String value) {
|
||||
MutableObj<String> getMutable(final String value) {
|
||||
return new MutableObj<>(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ public class MutableShortTest extends BaseMutableTest<Number, MutableShort> {
|
||||
* @return 值
|
||||
*/
|
||||
@Override
|
||||
MutableShort getMutable(Number value) {
|
||||
MutableShort getMutable(final Number value) {
|
||||
return new MutableShort(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ public class MutableTripleTest extends BaseMutableTest<MutableTriple<String, Str
|
||||
* @return 值
|
||||
*/
|
||||
@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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,9 +30,9 @@ public class BoundTest {
|
||||
@Test
|
||||
@DisplayName("测试相邻区间合并")
|
||||
void testUnionIfIntersectedWithAdjacentRanges() {
|
||||
BoundedRange<Integer> range1 = BoundedRange.close(1, 3);
|
||||
BoundedRange<Integer> range2 = BoundedRange.close(3, 5);
|
||||
BoundedRange<Integer> result = BoundedRangeOperation.unionIfIntersected(range1, range2);
|
||||
final BoundedRange<Integer> range1 = BoundedRange.close(1, 3);
|
||||
final BoundedRange<Integer> range2 = BoundedRange.close(3, 5);
|
||||
final BoundedRange<Integer> result = BoundedRangeOperation.unionIfIntersected(range1, range2);
|
||||
|
||||
assertEquals(Bound.atLeast(1), result.getLowerBound());
|
||||
assertEquals(Bound.atMost(5), result.getUpperBound());
|
||||
@ -40,8 +40,8 @@ public class BoundTest {
|
||||
|
||||
@Test
|
||||
void isDisjointTest(){
|
||||
BoundedRange<Integer> range1 = BoundedRange.close(1, 3);
|
||||
BoundedRange<Integer> range2 = BoundedRange.close(3, 5);
|
||||
final BoundedRange<Integer> range1 = BoundedRange.close(1, 3);
|
||||
final BoundedRange<Integer> range2 = BoundedRange.close(3, 5);
|
||||
// 点重合,相交
|
||||
assertFalse(range1.isDisjoint(range2));
|
||||
}
|
||||
|
||||
@ -43,9 +43,9 @@ public class RangeTest {
|
||||
@Test
|
||||
@DisplayName("测试不包含起始元素的迭代")
|
||||
void testIteratorWithoutIncludeStart() {
|
||||
Range<Integer> range = new Range<>(1, 5, (current, end, index) -> current + 1, false, true);
|
||||
List<Integer> elements = new ArrayList<>();
|
||||
for (Integer i : range) {
|
||||
final Range<Integer> range = new Range<>(1, 5, (current, end, index) -> current + 1, false, true);
|
||||
final List<Integer> elements = new ArrayList<>();
|
||||
for (final Integer i : range) {
|
||||
elements.add(i);
|
||||
}
|
||||
|
||||
|
||||
@ -24,8 +24,8 @@ class PhantomObjTest {
|
||||
@Test
|
||||
@DisplayName("测试 equals 方法与不同引用对象比较")
|
||||
void testEqualsWithDifferentReferent() {
|
||||
String differentObject = "different";
|
||||
PhantomObj<String> anotherPhantomObj = new PhantomObj<>(differentObject, queue);
|
||||
final String differentObject = "different";
|
||||
final PhantomObj<String> anotherPhantomObj = new PhantomObj<>(differentObject, queue);
|
||||
assertFalse(phantomObj.equals(anotherPhantomObj));
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ public class IncrementSelectorTest {
|
||||
*/
|
||||
@Test
|
||||
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("B", selector.select()); // 第二次调用应返回第二个元素
|
||||
|
||||
@ -28,16 +28,16 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
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")));
|
||||
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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
final Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
source.put(1, Arrays.asList("a", "b", "c"));
|
||||
map.putAll(source);
|
||||
Assertions.assertEquals(1, map.size());
|
||||
@ -46,7 +46,7 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
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, "b"));
|
||||
Assertions.assertTrue(map.putValue(1, "c"));
|
||||
@ -56,12 +56,12 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
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.assertEquals(1, map.size());
|
||||
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, "f"));
|
||||
map.putAllValues(source);
|
||||
@ -70,14 +70,14 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
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.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
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(2, "a", "b", "c"));
|
||||
|
||||
@ -92,7 +92,7 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
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(2, "a", "b", "c"));
|
||||
|
||||
@ -107,7 +107,7 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
public void removeValueTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertFalse(map.removeValue(1, "d"));
|
||||
Assertions.assertTrue(map.removeValue(1, "c"));
|
||||
@ -116,7 +116,7 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
public void removeAllValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f")));
|
||||
Assertions.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c")));
|
||||
@ -125,7 +125,7 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
public void removeValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertFalse(map.removeValues(1, "e", "f"));
|
||||
Assertions.assertTrue(map.removeValues(1, "b", "c"));
|
||||
@ -134,7 +134,7 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
public void getValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertEquals(Collections.emptyList(), map.getValues(2));
|
||||
Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.getValues(1));
|
||||
@ -142,7 +142,7 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
public void sizeTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertEquals(0, map.size(2));
|
||||
Assertions.assertEquals(3, map.size(1));
|
||||
@ -150,10 +150,10 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
public void allForEachTest() {
|
||||
MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new CollectionValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
List<Integer> keys = new ArrayList<>();
|
||||
List<String> values = new ArrayList<>();
|
||||
final List<Integer> keys = new ArrayList<>();
|
||||
final List<String> values = new ArrayList<>();
|
||||
map.allForEach((k, v) -> {
|
||||
keys.add(k);
|
||||
values.add(v);
|
||||
@ -164,7 +164,7 @@ public class CollectionValueMapTest {
|
||||
|
||||
@Test
|
||||
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(2, Arrays.asList("d", "e"));
|
||||
Assertions.assertEquals(
|
||||
|
||||
@ -28,16 +28,16 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
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")));
|
||||
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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
final MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
final Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
source.put(1, Arrays.asList("a", "b", "c"));
|
||||
map.putAll(source);
|
||||
Assertions.assertEquals(1, map.size());
|
||||
@ -46,7 +46,7 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
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, "b"));
|
||||
Assertions.assertTrue(map.putValue(1, "c"));
|
||||
@ -56,12 +56,12 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
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.assertEquals(1, map.size());
|
||||
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, "f"));
|
||||
map.putAllValues(source);
|
||||
@ -70,14 +70,14 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
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.assertEquals(Arrays.asList("a", "b", "c"), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeValueTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertFalse(map.removeValue(1, "d"));
|
||||
Assertions.assertTrue(map.removeValue(1, "c"));
|
||||
@ -86,7 +86,7 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
public void removeAllValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f")));
|
||||
Assertions.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c")));
|
||||
@ -95,7 +95,7 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
public void removeValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertFalse(map.removeValues(1, "e", "f"));
|
||||
Assertions.assertTrue(map.removeValues(1, "b", "c"));
|
||||
@ -104,7 +104,7 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
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(2, "a", "b", "c"));
|
||||
|
||||
@ -119,7 +119,7 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
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(2, "a", "b", "c"));
|
||||
|
||||
@ -134,7 +134,7 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
public void getValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertEquals(Collections.emptyList(), map.getValues(2));
|
||||
Assertions.assertEquals(Arrays.asList("a", "b", "c"), map.getValues(1));
|
||||
@ -142,7 +142,7 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
public void sizeTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertEquals(0, map.size(2));
|
||||
Assertions.assertEquals(3, map.size(1));
|
||||
@ -150,10 +150,10 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
public void allForEachTest() {
|
||||
MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new ListValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
List<Integer> keys = new ArrayList<>();
|
||||
List<String> values = new ArrayList<>();
|
||||
final List<Integer> keys = new ArrayList<>();
|
||||
final List<String> values = new ArrayList<>();
|
||||
map.allForEach((k, v) -> {
|
||||
keys.add(k);
|
||||
values.add(v);
|
||||
@ -164,7 +164,7 @@ public class ListValueMapTest {
|
||||
|
||||
@Test
|
||||
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(2, Arrays.asList("d", "e"));
|
||||
Assertions.assertEquals(
|
||||
|
||||
@ -28,16 +28,16 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
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")));
|
||||
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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
final MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
final Map<Integer, Collection<String>> source = new HashMap<>();
|
||||
source.put(1, Arrays.asList("a", "b", "c"));
|
||||
map.putAll(source);
|
||||
Assertions.assertEquals(1, map.size());
|
||||
@ -46,7 +46,7 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
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, "b"));
|
||||
Assertions.assertTrue(map.putValue(1, "c"));
|
||||
@ -56,12 +56,12 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
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.assertEquals(1, map.size());
|
||||
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.assertFalse(map.putValue(1, "e"));
|
||||
Assertions.assertTrue(map.putValue(1, "f"));
|
||||
@ -72,14 +72,14 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
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.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeValueTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertFalse(map.removeValue(1, "d"));
|
||||
Assertions.assertTrue(map.removeValue(1, "c"));
|
||||
@ -88,7 +88,7 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
public void removeAllValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertFalse(map.removeAllValues(1, Arrays.asList("e", "f")));
|
||||
Assertions.assertTrue(map.removeAllValues(1, Arrays.asList("b", "c")));
|
||||
@ -97,7 +97,7 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
public void removeValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertFalse(map.removeValues(1, "e", "f"));
|
||||
Assertions.assertTrue(map.removeValues(1, "b", "c"));
|
||||
@ -106,7 +106,7 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
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(2, "a", "b", "c"));
|
||||
|
||||
@ -121,7 +121,7 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
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(2, "a", "b", "c"));
|
||||
|
||||
@ -136,7 +136,7 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
public void getValuesTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertEquals(Collections.emptyList(), map.getValues(2));
|
||||
Assertions.assertEquals(new HashSet<>(Arrays.asList("a", "b", "c")), map.getValues(1));
|
||||
@ -144,7 +144,7 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
public void sizeTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
Assertions.assertEquals(0, map.size(2));
|
||||
Assertions.assertEquals(3, map.size(1));
|
||||
@ -152,10 +152,10 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
public void allForEachTest() {
|
||||
MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
final MultiValueMap<Integer, String> map = new SetValueMap<>();
|
||||
map.putValues(1, "a", "b", "c");
|
||||
List<Integer> keys = new ArrayList<>();
|
||||
List<String> values = new ArrayList<>();
|
||||
final List<Integer> keys = new ArrayList<>();
|
||||
final List<String> values = new ArrayList<>();
|
||||
map.allForEach((k, v) -> {
|
||||
keys.add(k);
|
||||
values.add(v);
|
||||
@ -166,7 +166,7 @@ public class SetValueMapTest {
|
||||
|
||||
@Test
|
||||
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(2, Arrays.asList("d", "e"));
|
||||
Assertions.assertEquals(
|
||||
|
||||
@ -27,7 +27,7 @@ public class TolerantMapTest {
|
||||
|
||||
@Test
|
||||
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("tuesday", "星期二");
|
||||
|
||||
@ -39,7 +39,7 @@ public class TolerantMapTest {
|
||||
|
||||
@Test
|
||||
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("tuesday", "星期二");
|
||||
|
||||
@ -50,7 +50,7 @@ public class TolerantMapTest {
|
||||
|
||||
@Test
|
||||
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("tuesday", "星期二");
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ public class MoneyTest {
|
||||
|
||||
@Test
|
||||
public void currencyScalingTest() {
|
||||
Money jpyMoney = new Money(0, Currency.getInstance("JPY"));
|
||||
final Money jpyMoney = new Money(0, Currency.getInstance("JPY"));
|
||||
jpyMoney.setAmount(BigDecimal.ONE);
|
||||
assertEquals(1, jpyMoney.getCent());
|
||||
}
|
||||
|
||||
@ -49,8 +49,8 @@ public class FieldUtilTest {
|
||||
// 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。
|
||||
fields = FieldUtil.getFields(TestSubUser.class);
|
||||
assertEquals(4, fields.length);
|
||||
List<Field> idFieldList = Arrays.stream(fields).filter(f -> Objects.equals(f.getName(), TestSubUser.Fields.id)).collect(Collectors.toList());
|
||||
Field firstIdField = CollUtil.getFirst(idFieldList);
|
||||
final List<Field> idFieldList = Arrays.stream(fields).filter(f -> Objects.equals(f.getName(), TestSubUser.Fields.id)).collect(Collectors.toList());
|
||||
final Field firstIdField = CollUtil.getFirst(idFieldList);
|
||||
assertEquals(Objects.requireNonNull(firstIdField).getDeclaringClass().getName(), TestSubUser.class.getName());
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ public class FieldUtilTest {
|
||||
public void getFieldMapTest() {
|
||||
// 获取指定类中字段名和字段对应的有序Map,包括其父类中的字段
|
||||
// 如果子类与父类中存在同名字段,则后者覆盖前者。
|
||||
Map<String, Field> fieldMap = FieldUtil.getFieldMap(TestSubUser.class);
|
||||
final Map<String, Field> fieldMap = FieldUtil.getFieldMap(TestSubUser.class);
|
||||
assertEquals(3, fieldMap.size());
|
||||
}
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ public class EasyStreamTest {
|
||||
@Test
|
||||
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-1", 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)
|
||||
.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);
|
||||
|
||||
// 按广度度优先遍历树结构,忽略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"))
|
||||
.forEach(node1 -> filteredNodes.add(node1.id));
|
||||
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 final String id;
|
||||
private List<Node> children;
|
||||
private Node(String id, List<Node> children) {
|
||||
private Node(final String id, final List<Node> children) {
|
||||
this.id = id;
|
||||
this.children = children;
|
||||
}
|
||||
public Node(String id) {
|
||||
public Node(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -33,25 +33,25 @@ class HierarchyIteratorTest {
|
||||
|
||||
@Test
|
||||
void testNoSuchElementException() {
|
||||
Node node = createTree();
|
||||
final Node node = createTree();
|
||||
// 根节点也被忽略,将会抛出异常
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> HierarchyIterator.depthFirst(node, node1 -> node1.children, node1 -> false));
|
||||
// 忽略所有节点,将会抛出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.assertThrows(NoSuchElementException.class, iterator::next);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDepthFirstWithFilter() {
|
||||
Node node = createTree();
|
||||
final Node node = createTree();
|
||||
// 按深度度优先遍历树结构,忽略id为1-1的节点与以其为根节点的子树
|
||||
List<String> nodes = new ArrayList<>();
|
||||
HierarchyIterator<Node> iterator = HierarchyIterator.depthFirst(
|
||||
final List<String> nodes = new ArrayList<>();
|
||||
final HierarchyIterator<Node> iterator = HierarchyIterator.depthFirst(
|
||||
node, node1 -> node1.children, node1 -> !node1.id.equals("1-1")
|
||||
);
|
||||
while (iterator.hasNext()) {
|
||||
Node node1 = iterator.next();
|
||||
final Node node1 = iterator.next();
|
||||
nodes.add(node1.id);
|
||||
}
|
||||
Assertions.assertEquals(Arrays.asList("1", "1-2", "1-2-1", "1-2-2"), nodes);
|
||||
@ -59,12 +59,12 @@ class HierarchyIteratorTest {
|
||||
|
||||
@Test
|
||||
void testDepthFirst() {
|
||||
Node node = createTree();
|
||||
final Node node = createTree();
|
||||
// 按深度度优先遍历树结构
|
||||
List<String> nodes = new ArrayList<>();
|
||||
HierarchyIterator<Node> iterator = HierarchyIterator.depthFirst(node, node1 -> node1.children);
|
||||
final List<String> nodes = new ArrayList<>();
|
||||
final HierarchyIterator<Node> iterator = HierarchyIterator.depthFirst(node, node1 -> node1.children);
|
||||
while (iterator.hasNext()) {
|
||||
Node node1 = iterator.next();
|
||||
final Node node1 = iterator.next();
|
||||
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);
|
||||
@ -72,14 +72,14 @@ class HierarchyIteratorTest {
|
||||
|
||||
@Test
|
||||
void testBreadthFirstWithFilter() {
|
||||
Node node = createTree();
|
||||
final Node node = createTree();
|
||||
// 按深度度优先遍历树结构,忽略id为1-1的节点与以其为根节点的子树
|
||||
List<String> nodes = new ArrayList<>();
|
||||
HierarchyIterator<Node> iterator = HierarchyIterator.breadthFirst(
|
||||
final List<String> nodes = new ArrayList<>();
|
||||
final HierarchyIterator<Node> iterator = HierarchyIterator.breadthFirst(
|
||||
node, node1 -> node1.children, node1 -> !node1.id.equals("1-1")
|
||||
);
|
||||
while (iterator.hasNext()) {
|
||||
Node node1 = iterator.next();
|
||||
final Node node1 = iterator.next();
|
||||
nodes.add(node1.id);
|
||||
}
|
||||
Assertions.assertEquals(Arrays.asList("1", "1-2", "1-2-1", "1-2-2"), nodes);
|
||||
@ -87,12 +87,12 @@ class HierarchyIteratorTest {
|
||||
|
||||
@Test
|
||||
void testBreadthFirst() {
|
||||
Node root = createGraph();
|
||||
final Node root = createGraph();
|
||||
// 按深度度优先遍历图结构
|
||||
List<String> nodes = new ArrayList<>();
|
||||
HierarchyIterator<Node> iterator = HierarchyIterator.breadthFirst(root, node -> node.children);
|
||||
final List<String> nodes = new ArrayList<>();
|
||||
final HierarchyIterator<Node> iterator = HierarchyIterator.breadthFirst(root, node -> node.children);
|
||||
while (iterator.hasNext()) {
|
||||
Node node = iterator.next();
|
||||
final Node node = iterator.next();
|
||||
nodes.add(node.id);
|
||||
}
|
||||
Assertions.assertEquals(Arrays.asList("1", "4", "2", "3"), nodes);
|
||||
@ -100,10 +100,10 @@ class HierarchyIteratorTest {
|
||||
|
||||
private static Node createGraph() {
|
||||
// 构建一个包含四个节点的图,每一个节点都有两个相邻节点
|
||||
Node node1 = new Node("1");
|
||||
Node node2 = new Node("2");
|
||||
Node node3 = new Node("3");
|
||||
Node node4 = new Node("4");
|
||||
final Node node1 = new Node("1");
|
||||
final Node node2 = new Node("2");
|
||||
final Node node3 = new Node("3");
|
||||
final Node node4 = new Node("4");
|
||||
node1.children = Arrays.asList(node4, node2);
|
||||
node2.children = Arrays.asList(node1, node3);
|
||||
node3.children = Arrays.asList(node2, node4);
|
||||
@ -131,11 +131,11 @@ class HierarchyIteratorTest {
|
||||
private static class Node {
|
||||
private final String id;
|
||||
private List<Node> children;
|
||||
private Node(String id, List<Node> children) {
|
||||
private Node(final String id, final List<Node> children) {
|
||||
this.id = id;
|
||||
this.children = children;
|
||||
}
|
||||
public Node(String id) {
|
||||
public Node(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,13 +238,13 @@ public class ObjUtilTest {
|
||||
|
||||
@Test
|
||||
public void testLengthConsumesIterator() {
|
||||
List<String> list = Arrays.asList("a", "b", "c");
|
||||
Iterator<String> iterator = list.iterator();
|
||||
final List<String> list = Arrays.asList("a", "b", "c");
|
||||
final Iterator<String> iterator = list.iterator();
|
||||
// 迭代器第一次调用length
|
||||
int length1 = ObjUtil.length(iterator);
|
||||
final int length1 = ObjUtil.length(iterator);
|
||||
assertEquals(3, length1);
|
||||
// 迭代器第二次调用length - 迭代器已经被消耗,返回0
|
||||
int length2 = ObjUtil.length(iterator);
|
||||
final int length2 = ObjUtil.length(iterator);
|
||||
assertEquals(0, length2); // 但当前实现会重新遍历,但iterator已经没有元素了
|
||||
// 尝试使用迭代器 - 已经无法使用
|
||||
assertFalse(iterator.hasNext());
|
||||
@ -252,13 +252,13 @@ public class ObjUtilTest {
|
||||
|
||||
@Test
|
||||
public void testLengthConsumesEnumeration() {
|
||||
Vector<String> vector = new Vector<>(Arrays.asList("a", "b", "c"));
|
||||
Enumeration<String> enumeration = vector.elements();
|
||||
final Vector<String> vector = new Vector<>(Arrays.asList("a", "b", "c"));
|
||||
final Enumeration<String> enumeration = vector.elements();
|
||||
// 第一次调用length
|
||||
int length1 = ObjUtil.length(enumeration);
|
||||
final int length1 = ObjUtil.length(enumeration);
|
||||
assertEquals(3, length1);
|
||||
// 第二次调用length - 枚举已经被消耗
|
||||
int length2 = ObjUtil.length(enumeration);
|
||||
final int length2 = ObjUtil.length(enumeration);
|
||||
assertEquals(0, length2);
|
||||
// 枚举已经无法使用
|
||||
assertFalse(enumeration.hasMoreElements());
|
||||
|
||||
@ -13,7 +13,7 @@ public class TaskTableFactory {
|
||||
* @param config 定时任务配置
|
||||
* @return 任务表
|
||||
*/
|
||||
public static TaskTable create(CronConfig config) {
|
||||
public static TaskTable create(final CronConfig config) {
|
||||
return config.isUseTriggerQueue() ? new TriggerQueueTaskTable() : new MatchTaskTable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ public class TriggerQueueTaskTable extends TaskTable {
|
||||
}
|
||||
|
||||
@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);
|
||||
// 将下一个触发时间及任务添加到队列中
|
||||
this.triggerQueue.offer(new TriggerTime(id, pattern.nextMatchFromNow()));
|
||||
@ -48,7 +48,7 @@ public class TriggerQueueTaskTable extends TaskTable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(String id) {
|
||||
public boolean remove(final String id) {
|
||||
// 移除队列中的任务
|
||||
this.triggerQueue.removeIf(task -> StrUtil.equals(task.id(), id));
|
||||
return super.remove(id);
|
||||
@ -56,7 +56,7 @@ public class TriggerQueueTaskTable extends TaskTable {
|
||||
}
|
||||
|
||||
@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));
|
||||
// 将下一个触发时间及任务添加到队列中
|
||||
@ -131,7 +131,7 @@ public class TriggerQueueTaskTable extends TaskTable {
|
||||
*/
|
||||
private record TriggerTime(String id, long timestamp) implements Comparable<TriggerTime> {
|
||||
@Override
|
||||
public int compareTo(TriggerTime other) {
|
||||
public int compareTo(final TriggerTime other) {
|
||||
return Long.compare(this.timestamp, other.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ public class CronPattern {
|
||||
* @return 匹配到的下一个时间时间戳
|
||||
* @since 7.0.0
|
||||
*/
|
||||
public long nextMatch(long millis) {
|
||||
public long nextMatch(final long millis) {
|
||||
return nextMatch(CalendarUtil.calendar(millis)).getTimeInMillis();
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ import cn.hutool.v7.core.lang.Console;
|
||||
import cn.hutool.v7.cron.CronUtil;
|
||||
|
||||
public class SimpleDemo {
|
||||
public static void main(String[] args) {
|
||||
public static void main(final String[] args) {
|
||||
// 打开秒匹配
|
||||
CronUtil.setMatchSecond(true);
|
||||
// 添加任务
|
||||
|
||||
@ -5,7 +5,7 @@ import cn.hutool.v7.cron.CronConfig;
|
||||
import cn.hutool.v7.cron.Scheduler;
|
||||
|
||||
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));
|
||||
scheduler.schedule("*/10 * * * * *",
|
||||
() -> Console.log("Hutool task */10 running at: [{}]", System.currentTimeMillis()));
|
||||
|
||||
@ -17,8 +17,8 @@
|
||||
package cn.hutool.v7.cron.timingwheel;
|
||||
|
||||
public class Issue3090Test {
|
||||
public static void main(String[] args) {
|
||||
SystemTimer timer = new SystemTimer();
|
||||
public static void main(final String[] args) {
|
||||
final SystemTimer timer = new SystemTimer();
|
||||
timer.setDelayQueueTimeout(1000);
|
||||
timer.start();
|
||||
timer.addTask(new TimerTask(() -> {
|
||||
|
||||
@ -211,7 +211,7 @@ public class Sign extends BaseAsymmetric<Sign> {
|
||||
// If the certificate is of type X509Certificate,
|
||||
// we should check whether it has a Key Usage
|
||||
// extension marked as critical.
|
||||
if (certificate instanceof X509Certificate cert) {
|
||||
if (certificate instanceof final X509Certificate cert) {
|
||||
// Check whether the cert has a key usage extension
|
||||
// marked as a critical extension.
|
||||
// The OID for KeyUsage extension is 2.5.29.15.
|
||||
|
||||
@ -431,7 +431,7 @@ public class Entity extends Dict {
|
||||
return SqlUtil.clobToStr((Clob) obj);
|
||||
} else if (obj instanceof Blob) {
|
||||
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 super.getStr(field, defaultValue);
|
||||
|
||||
@ -64,10 +64,10 @@ public class TomlConfigParser implements ConfigParser {
|
||||
tomlContent = ResourceUtil.readUtf8Str(tomlPath);
|
||||
} else {
|
||||
// 读取默认TOML文件
|
||||
for (String defaultDbTomlPath : DEFAULT_DB_TOML_PATHS) {
|
||||
for (final String defaultDbTomlPath : DEFAULT_DB_TOML_PATHS) {
|
||||
try {
|
||||
tomlContent = ResourceUtil.readUtf8Str(defaultDbTomlPath);
|
||||
} catch (NoResourceException e) {
|
||||
} catch (final NoResourceException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@ -83,12 +83,12 @@ public class TomlConfigParser implements ConfigParser {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public DbConfig parse(final String group) {
|
||||
Map<String, Object> groupData;
|
||||
final Map<String, Object> groupData;
|
||||
|
||||
if (StrUtil.isEmpty(group)) {
|
||||
groupData = this.tomlData;
|
||||
} else {
|
||||
Object groupObj = this.tomlData.get(group);
|
||||
final Object groupObj = this.tomlData.get(group);
|
||||
if (groupObj instanceof Map) {
|
||||
// 新建一个Map,避免继承属性影响原数据
|
||||
groupData = new HashMap<>((Map<String, Object>) groupObj);
|
||||
@ -109,7 +109,7 @@ public class TomlConfigParser implements ConfigParser {
|
||||
/**
|
||||
* 如果目标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)) {
|
||||
target.put(key, this.tomlData.get(key));
|
||||
}
|
||||
@ -118,9 +118,9 @@ public class TomlConfigParser implements ConfigParser {
|
||||
/**
|
||||
* 将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)) {
|
||||
throw new DbException("No JDBC URL!");
|
||||
}
|
||||
@ -131,27 +131,27 @@ public class TomlConfigParser implements ConfigParser {
|
||||
driver = DriverUtil.identifyDriver(url);
|
||||
}
|
||||
|
||||
DbConfig dbConfig = DbConfig.of()
|
||||
final DbConfig dbConfig = DbConfig.of()
|
||||
.setUrl(url)
|
||||
.setDriver(driver)
|
||||
.setUser(getAndRemoveString(data, DSKeys.KEY_ALIAS_USER))
|
||||
.setPass(getAndRemoveString(data, DSKeys.KEY_ALIAS_PASSWORD));
|
||||
|
||||
// SQL日志
|
||||
SqlLogFilter sqlLogFilter = getSqlLogFilter(data);
|
||||
final SqlLogFilter sqlLogFilter = getSqlLogFilter(data);
|
||||
if (sqlLogFilter != null) {
|
||||
dbConfig.addSqlFilter(sqlLogFilter);
|
||||
}
|
||||
|
||||
// 大小写等配置
|
||||
Boolean caseInsensitive = getAndRemoveBoolean(data, DSKeys.KEY_CASE_INSENSITIVE);
|
||||
final Boolean caseInsensitive = getAndRemoveBoolean(data, DSKeys.KEY_CASE_INSENSITIVE);
|
||||
if (null != caseInsensitive) {
|
||||
dbConfig.setCaseInsensitive(caseInsensitive);
|
||||
}
|
||||
|
||||
// 连接配置
|
||||
for (String key : DSKeys.KEY_CONN_PROPS) {
|
||||
String connValue = getAndRemoveString(data, key);
|
||||
for (final String key : DSKeys.KEY_CONN_PROPS) {
|
||||
final String connValue = getAndRemoveString(data, key);
|
||||
if (StrUtil.isNotBlank(connValue)) {
|
||||
dbConfig.addConnProps(key, connValue);
|
||||
}
|
||||
@ -178,7 +178,7 @@ public class TomlConfigParser implements ConfigParser {
|
||||
/**
|
||||
* 获取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);
|
||||
if (isShowSql == null || !isShowSql) {
|
||||
return null;
|
||||
@ -191,9 +191,9 @@ public class TomlConfigParser implements ConfigParser {
|
||||
if (sqlLevelStr != null) {
|
||||
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);
|
||||
|
||||
return new SqlLogFilter(sqlLog);
|
||||
@ -206,9 +206,9 @@ public class TomlConfigParser implements ConfigParser {
|
||||
* @param keys 多个键
|
||||
* @return 字符串值
|
||||
*/
|
||||
private String getAndRemoveString(Map<String, Object> map, String... keys) {
|
||||
private String getAndRemoveString(final Map<String, Object> map, final String... keys) {
|
||||
Object value = null;
|
||||
for (String key : keys) {
|
||||
for (final String key : keys) {
|
||||
value = map.remove(key);
|
||||
if (null != value) {
|
||||
break;
|
||||
@ -224,9 +224,9 @@ public class TomlConfigParser implements ConfigParser {
|
||||
* @param keys 多个键
|
||||
* @return 布尔值
|
||||
*/
|
||||
private Boolean getAndRemoveBoolean(Map<String, Object> map, String... keys) {
|
||||
private Boolean getAndRemoveBoolean(final Map<String, Object> map, final String... keys) {
|
||||
Object value = null;
|
||||
for (String key : keys) {
|
||||
for (final String key : keys) {
|
||||
value = map.remove(key);
|
||||
if (null != value) {
|
||||
break;
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user