├── .gitignore ├── .idea ├── .gitignore ├── csdn_downloader.iml ├── dictionaries ├── encodings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── LICENSE ├── Makefile ├── README.md ├── pom.xml ├── public ├── domainnoh.jpg ├── download1.png ├── download2.png ├── download2R.png ├── download3.png ├── download3R.png ├── download4.png ├── download_success.jpg ├── register.png └── register2.png └── src └── com └── csdndownload ├── DownloadApplication.java ├── common └── ApiMeta.java ├── service ├── CsdnDownloadService.java └── impl │ └── CsdnDownloadServiceImpl.java └── utils ├── Assert.java ├── CastUtils.java └── CollectionUtils.java /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .idea/misc.xml 3 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/csdn_downloader.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/dictionaries: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 RedStone 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | push: 3 | git add -A && git commit -m "update" && git push 4 | 5 | 6 | pull: 7 | git pull 8 | 9 | 10 | 11 | package_pro: 12 | mvn clean package -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # csdn资源下载工具 2 | 3 | #### 介绍 4 | + csdn免积分下载工具 5 | + csdn免会员下载工具 6 | + csdnvip资源下载工具 7 | + csdn文章下载,免积分,免购买超级会员 8 | + 9 | 10 | #### 软件架构 11 | 采用spingboot + dubbo 架构设计 12 | 13 | #### 安装教程 14 | 15 | 1. 体验地址1(最快1) http://toolman.ddnsfree.com:9192/#/login?c=12 16 | 2. 体验地址2(最快2) http://toolman.dedyn.io:9192/#/login?c=12 17 | 3. 体验地址3(慢) http://servicedev.tpddns.cn:9192/#/login?c=12 18 | 4. 需要注册 并拥有qq,163等邮箱 19 | 20 | #### 使用说明 21 | 22 | 1. 复制需要下载页面的url(也即是浏览器地址栏的地址) 23 | ![看看](./public/download1.png) 24 | 2. 张贴到下载输入框的 25 | ![看看](./public/download3.png) 26 | 3. 点击下载 27 | ![看看](./public/download4.png) 28 | 29 | #### 参与贡献 30 | 31 | 1. Fork 本仓库 32 | 2. 新建 Feat_xxx 分支 33 | 3. 提交代码 34 | 4. 新建 Pull Request 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | org.springframework.boot 9 | spring-boot-starter-parent 10 | 2.5.2 11 | 12 | 13 | 14 | com.csdndownload 15 | downloader 16 | 1.0.0-SNAPSHOT 17 | 18 | 19 | 20 | 11 21 | 11 22 | UTF-8 23 | UTF-8 24 | 11 25 | 2.5.2 26 | 27 | 28 | 29 | 30 | jakarta.annotation 31 | jakarta.annotation-api 32 | 1.3.5 33 | 34 | 35 | org.hibernate.validator 36 | hibernate-validator 37 | 6.2.0.Final 38 | 39 | 40 | org.projectlombok 41 | lombok 42 | 1.18.16 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-dependency-plugin 51 | 3.1.1 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /public/domainnoh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigintpro/csdn_downloader/92f219d4ef5444fc0c180240eebd919e85d9e100/public/domainnoh.jpg -------------------------------------------------------------------------------- /public/download1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigintpro/csdn_downloader/92f219d4ef5444fc0c180240eebd919e85d9e100/public/download1.png -------------------------------------------------------------------------------- /public/download2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigintpro/csdn_downloader/92f219d4ef5444fc0c180240eebd919e85d9e100/public/download2.png -------------------------------------------------------------------------------- /public/download2R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigintpro/csdn_downloader/92f219d4ef5444fc0c180240eebd919e85d9e100/public/download2R.png -------------------------------------------------------------------------------- /public/download3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigintpro/csdn_downloader/92f219d4ef5444fc0c180240eebd919e85d9e100/public/download3.png -------------------------------------------------------------------------------- /public/download3R.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigintpro/csdn_downloader/92f219d4ef5444fc0c180240eebd919e85d9e100/public/download3R.png -------------------------------------------------------------------------------- /public/download4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigintpro/csdn_downloader/92f219d4ef5444fc0c180240eebd919e85d9e100/public/download4.png -------------------------------------------------------------------------------- /public/download_success.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigintpro/csdn_downloader/92f219d4ef5444fc0c180240eebd919e85d9e100/public/download_success.jpg -------------------------------------------------------------------------------- /public/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigintpro/csdn_downloader/92f219d4ef5444fc0c180240eebd919e85d9e100/public/register.png -------------------------------------------------------------------------------- /public/register2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigintpro/csdn_downloader/92f219d4ef5444fc0c180240eebd919e85d9e100/public/register2.png -------------------------------------------------------------------------------- /src/com/csdndownload/DownloadApplication.java: -------------------------------------------------------------------------------- 1 | package com.csdndownload; 2 | 3 | public class DownloadApplication { 4 | public static void main(String[] args) { 5 | SpringApplication.run(DownloadApplication.class, args); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/com/csdndownload/common/ApiMeta.java: -------------------------------------------------------------------------------- 1 | package com.csdndownload.common; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Target({ElementType.FIELD}) 6 | @Retention(RetentionPolicy.RUNTIME) 7 | @Inherited 8 | public @interface ApiMeta { 9 | 10 | /** 11 | * 名称 12 | * @return 13 | */ 14 | public String value() default ""; 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/com/csdndownload/service/CsdnDownloadService.java: -------------------------------------------------------------------------------- 1 | package com.csdndownload.service; 2 | 3 | import com.sun.istack.internal.NotNull; 4 | 5 | import java.util.concurrent.CompletableFuture; 6 | 7 | public interface CsdnDownloadService { 8 | 9 | /** 10 | * 下载csdn对应的资源 11 | * @param resourceId 资源ID 12 | * @param originUrl 资源url 13 | * @return 是否下载成功 14 | */ 15 | CompletableFuture downloadResource(@NotNull String resourceId, String originUrl); 16 | } 17 | -------------------------------------------------------------------------------- /src/com/csdndownload/service/impl/CsdnDownloadServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.csdndownload.service.impl; 2 | 3 | import com.csdndownload.service.CsdnDownloadService; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.concurrent.CompletableFuture; 8 | 9 | @Service 10 | public class CsdnDownloadServiceImpl implements CsdnDownloadService { 11 | 12 | @Autowired 13 | private ThreadPoolTaskExecutor threadPoolTaskExecutor; 14 | 15 | @Override 16 | public CompletableFuture downloadResource(String resourceId, String originUrl) { 17 | 18 | return CompletableFuture.supplyAsync(() -> { 19 | List excludeAccountIds = new ArrayList<>(); 20 | String lockPath = "csdn_" + resourceId; 21 | Lock lock = LockFactory.getInstance(lockPath); 22 | 23 | Boolean result = downloadResource(resourceId,originUrl, excludeAccountIds, 1, lock); 24 | try { 25 | lock.close(); 26 | }catch (Exception e){ 27 | log.error("downloadResource error happened:{}",e.getMessage(),e); 28 | } 29 | return result; 30 | 31 | }, threadPoolTaskExecutor); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/com/csdndownload/utils/Assert.java: -------------------------------------------------------------------------------- 1 | package com.csdndownload.utils; 2 | 3 | import com.sunday.commons.factory.MF; 4 | import lombok.extern.log4j.Log4j2; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | @Log4j2 11 | public class Assert { 12 | 13 | /** 14 | * 必须是true 15 | * 16 | * @param object 对象 17 | * @param message 错误消息 18 | */ 19 | public static void mustTrue(boolean object, String message) { 20 | if (!object) { 21 | throw new IllegalStateException(message); 22 | } 23 | } 24 | 25 | /** 26 | * 必须是true 27 | * 28 | * @param object 对象 29 | * @param message 错误消息 30 | * @param clue1 线索1 31 | */ 32 | public static void mustTrue(boolean object, String message, Object clue1) { 33 | if (!object) { 34 | throw new IllegalStateException(MF.m(message, clue1)); 35 | } 36 | } 37 | 38 | /** 39 | * 必须是true 40 | * 41 | * @param object 对象 42 | * @param message 错误消息 43 | * @param clue1 线索1 44 | * @param clue2 线索2 45 | */ 46 | public static void mustTrue(boolean object, String message, Object clue1, Object clue2) { 47 | if (!object) { 48 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 49 | } 50 | } 51 | 52 | /** 53 | * 必须是true 54 | * 55 | * @param object 对象 56 | * @param message 错误消息 57 | * @param clue1 线索1 58 | * @param clue2 线索2 59 | * @param clue3 线索3 60 | */ 61 | public static void mustTrue(boolean object, String message, Object clue1, Object clue2, Object clue3) { 62 | if (!object) { 63 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 64 | } 65 | } 66 | 67 | /** 68 | * 必须是false 69 | * 70 | * @param object 对象 71 | * @param message 错误消息 72 | */ 73 | public static void mustFalse(boolean object, String message) { 74 | if (object) { 75 | throw new IllegalStateException(message); 76 | } 77 | } 78 | 79 | /** 80 | * 必须是false 81 | * 82 | * @param object 对象 83 | * @param message 错误消息 84 | * @param clue1 线索1 85 | */ 86 | public static void mustFalse(boolean object, String message, Object clue1) { 87 | if (object) { 88 | throw new IllegalStateException(MF.m(message, clue1)); 89 | } 90 | } 91 | 92 | /** 93 | * 必须是false 94 | * 95 | * @param object 对象 96 | * @param message 错误消息 97 | * @param clue1 线索1 98 | * @param clue2 线索2 99 | */ 100 | public static void mustFalse(boolean object, String message, Object clue1, Object clue2) { 101 | if (object) { 102 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 103 | } 104 | } 105 | 106 | /** 107 | * 必须是false 108 | * 109 | * @param object 对象 110 | * @param message 错误消息 111 | * @param clue1 线索1 112 | * @param clue2 线索2 113 | * @param clue3 线索3 114 | */ 115 | public static void mustFalse(boolean object, String message, Object clue1, Object clue2, Object clue3) { 116 | if (object) { 117 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 118 | } 119 | } 120 | 121 | /** 122 | * 必须是null 123 | * 124 | * @param object 对象 125 | * @param message 错误消息 126 | */ 127 | public static void mustNull(Object object, String message) { 128 | if (object != null) { 129 | throw new IllegalStateException(message); 130 | } 131 | } 132 | 133 | /** 134 | * 必须是null 135 | * 136 | * @param object 对象 137 | * @param message 错误消息 138 | */ 139 | public static void mustNull(Object object, String message, Object clue1) { 140 | if (object != null) { 141 | throw new IllegalStateException(MF.m(message, clue1)); 142 | } 143 | } 144 | 145 | /** 146 | * 必须是null 147 | * 148 | * @param object 对象 149 | * @param message 错误消息 150 | */ 151 | public static void mustNull(Object object, String message, Object clue1, Object clue2) { 152 | if (object != null) { 153 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 154 | } 155 | } 156 | 157 | /** 158 | * 必须是null 159 | * 160 | * @param object 对象 161 | * @param message 错误消息 162 | */ 163 | public static void mustNull(Object object, String message, Object clue1, Object clue2, Object clue3) { 164 | if (object != null) { 165 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 166 | } 167 | } 168 | 169 | /** 170 | * 不能为空字符串 171 | * 172 | * @param object 对象 173 | * @param message 错误消息 174 | */ 175 | public static void mustNotBlank(String object, String message) { 176 | if (object == null || "".equals(object)) { 177 | throw new IllegalStateException(message); 178 | } 179 | } 180 | 181 | /** 182 | * 不能为空字符串 183 | * 184 | * @param object 对象 185 | * @param message 错误消息 186 | */ 187 | public static void mustNotBlank(String object, String message, Object clue1) { 188 | if (object == null || "".equals(object)) { 189 | throw new IllegalStateException(MF.m(message, clue1)); 190 | } 191 | } 192 | 193 | /** 194 | * 不能为空字符串 195 | * 196 | * @param object 对象 197 | * @param message 错误消息 198 | */ 199 | public static void mustNotBlank(String object, String message, Object clue1, Object clue2) { 200 | if (object == null || "".equals(object)) { 201 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 202 | } 203 | } 204 | 205 | /** 206 | * 不能为空字符串 207 | * 208 | * @param object 对象 209 | * @param message 错误消息 210 | */ 211 | public static void mustNotBlank(String object, String message, Object clue1, Object clue2, Object clue3) { 212 | if (object == null || "".equals(object)) { 213 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 214 | } 215 | } 216 | 217 | /** 218 | * 必须为long类型,或者可以转换成long类型 219 | * 220 | * @param value value 221 | * @param message 错误消息 222 | */ 223 | public static void mustLongType(String value, String message) { 224 | if (value == null || "".equals(value)) { 225 | throw new IllegalStateException(message); 226 | } 227 | try { 228 | Long.parseLong(value); 229 | } catch (Exception e) { 230 | throw new IllegalStateException(message); 231 | } 232 | } 233 | 234 | /** 235 | * 必须为long类型,或者可以转换成long类型 236 | * 237 | * @param value value 238 | * @param message 错误消息 239 | * @param clue1 线索1 240 | */ 241 | public static void mustLongType(String value, String message, Object clue1) { 242 | if (value == null || "".equals(value)) { 243 | throw new IllegalStateException(MF.m(message, clue1)); 244 | } 245 | try { 246 | Long.parseLong(value); 247 | } catch (Exception e) { 248 | throw new IllegalStateException(MF.m(message, clue1)); 249 | } 250 | } 251 | 252 | /** 253 | * 必须为long类型,或者可以转换成long类型 254 | * 255 | * @param value value 256 | * @param message 错误消息 257 | * @param clue1 线索1 258 | * @param clue2 线索2 259 | */ 260 | public static void mustLongType(String value, String message, Object clue1, Object clue2) { 261 | if (value == null || "".equals(value)) { 262 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 263 | } 264 | try { 265 | Long.parseLong(value); 266 | } catch (Exception e) { 267 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 268 | } 269 | } 270 | 271 | /** 272 | * 必须为long类型,或者可以转换成long类型 273 | * 274 | * @param value value 275 | * @param message 错误消息 276 | * @param clue1 线索1 277 | * @param clue2 线索2 278 | * @param clue3 线索3 279 | */ 280 | public static void mustLongType(String value, String message, Object clue1, Object clue2, Object clue3) { 281 | if (value == null || "".equals(value)) { 282 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 283 | } 284 | try { 285 | Long.parseLong(value); 286 | } catch (Exception e) { 287 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 288 | } 289 | } 290 | 291 | /** 292 | * 不能为空 293 | * 294 | * @param object 对象 295 | * @param message 错误消息 296 | */ 297 | public static void notNull(T object, String message) { 298 | if (object == null) { 299 | throw new IllegalArgumentException(message); 300 | } 301 | } 302 | 303 | /** 304 | * 不能为空 305 | * 306 | * @param object 对象 307 | * @param message 错误消息 308 | * @param clue1 线索1 309 | */ 310 | public static void notNull(T object, String message, Object clue1) { 311 | if (object == null) { 312 | throw new IllegalStateException(MF.m(message, clue1)); 313 | } 314 | } 315 | 316 | /** 317 | * 不能为空 318 | * 319 | * @param object 对象 320 | * @param message 错误消息 321 | * @param clue1 线索1 322 | * @param clue2 线索2 323 | */ 324 | public static void notNull(T object, String message, Object clue1, Object clue2) { 325 | if (object == null) { 326 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 327 | } 328 | } 329 | 330 | /** 331 | * 不能为空 332 | * 333 | * @param object 对象 334 | * @param message 错误消息 335 | * @param clue1 线索1 336 | * @param clue2 线索2 337 | * @param clue3 线索3 338 | */ 339 | public static void notNull(T object, String message, Object clue1, Object clue2, Object clue3) { 340 | if (object == null) { 341 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 342 | } 343 | } 344 | 345 | /** 346 | * 不能为空 347 | * 348 | * @param list 349 | * @param message 错误消息 350 | */ 351 | public static void notEmpty(List list, String message) { 352 | 353 | if (list == null || list.isEmpty()) { 354 | throw new IllegalArgumentException(message); 355 | } 356 | } 357 | 358 | public static void notEmpty(byte[] array, String message) { 359 | 360 | if (array == null || array.length <= 0) { 361 | throw new IllegalArgumentException(message); 362 | } 363 | } 364 | 365 | /** 366 | * 不能为空 367 | * 368 | * @param list 369 | * @param message 错误消息 370 | * @param clue1 线索1 371 | */ 372 | public static void notEmpty(List list, String message, Object clue1) { 373 | 374 | if (list == null || list.isEmpty()) { 375 | throw new IllegalStateException(MF.m(message, clue1)); 376 | } 377 | } 378 | 379 | /** 380 | * 不能为空 381 | * 382 | * @param list 383 | * @param message 错误消息 384 | * @param clue1 线索1 385 | * @param clue2 线索2 386 | */ 387 | public static void notEmpty(List list, String message, Object clue1, Object clue2) { 388 | 389 | if (list == null || list.isEmpty()) { 390 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 391 | } 392 | } 393 | 394 | /** 395 | * 不能为空 396 | * 397 | * @param list 398 | * @param message 错误消息 399 | * @param clue1 线索1 400 | * @param clue2 线索2 401 | * @param clue3 线索3 402 | */ 403 | public static void notEmpty(List list, String message, Object clue1, Object clue2, Object clue3) { 404 | 405 | if (list == null || list.isEmpty()) { 406 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 407 | } 408 | } 409 | 410 | /** 411 | * 不能为空 412 | * 413 | * @param map map 414 | * @param message 错误消息 415 | */ 416 | public static void notEmpty(Map map, String message) { 417 | 418 | if (map == null || map.isEmpty()) { 419 | throw new IllegalArgumentException(message); 420 | } 421 | } 422 | 423 | /** 424 | * 不能为空 425 | * 426 | * @param map map 427 | * @param message 错误消息 428 | * @param clue1 线索1 429 | */ 430 | public static void notEmpty(Map map, String message, Object clue1) { 431 | 432 | if (map == null || map.isEmpty()) { 433 | throw new IllegalStateException(MF.m(message, clue1)); 434 | } 435 | } 436 | 437 | /** 438 | * 不能为空 439 | * 440 | * @param map map 441 | * @param message 错误消息 442 | * @param clue1 线索1 443 | * @param clue2 线索2 444 | */ 445 | public static void notEmpty(Map map, String message, Object clue1, Object clue2) { 446 | 447 | if (map == null || map.isEmpty()) { 448 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 449 | } 450 | } 451 | 452 | /** 453 | * 不能为空 454 | * 455 | * @param map map 456 | * @param message 错误消息 457 | * @param clue1 线索1 458 | * @param clue2 线索2 459 | * @param clue3 线索3 460 | */ 461 | public static void notEmpty(Map map, String message, Object clue1, Object clue2, Object clue3) { 462 | 463 | if (map == null || map.isEmpty()) { 464 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 465 | } 466 | } 467 | 468 | /** 469 | * 不能为空 470 | * 471 | * @param set set 472 | * @param message 错误消息 473 | */ 474 | public static void notEmpty(Set set, String message) { 475 | if (set == null || set.isEmpty()) { 476 | throw new IllegalArgumentException(message); 477 | } 478 | } 479 | 480 | /** 481 | * 不能为空 482 | * 483 | * @param set set 484 | * @param message 错误消息 485 | * @param clue1 线索1 486 | */ 487 | public static void notEmpty(Set set, String message, Object clue1) { 488 | if (set == null || set.isEmpty()) { 489 | throw new IllegalStateException(MF.m(message, clue1)); 490 | } 491 | } 492 | 493 | /** 494 | * 不能为空 495 | * 496 | * @param set set 497 | * @param message 错误消息 498 | * @param clue1 线索1 499 | * @param clue2 线索2 500 | */ 501 | public static void notEmpty(Set set, String message, Object clue1, Object clue2) { 502 | if (set == null || set.isEmpty()) { 503 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 504 | } 505 | } 506 | 507 | /** 508 | * 不能为空 509 | * 510 | * @param set set 511 | * @param message 错误消息 512 | * @param clue1 线索1 513 | * @param clue2 线索2 514 | * @param clue3 线索3 515 | */ 516 | public static void notEmpty(Set set, String message, Object clue1, Object clue2, Object clue3) { 517 | if (set == null || set.isEmpty()) { 518 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 519 | } 520 | } 521 | 522 | /** 523 | * 不能为空 524 | * 525 | * @param array array 526 | * @param message 错误消息 527 | */ 528 | public static void notEmpty(T[] array, String message) { 529 | if (array == null || array.length == 0) { 530 | throw new IllegalArgumentException(message); 531 | } 532 | } 533 | 534 | /** 535 | * 不能为空 536 | * 537 | * @param array array 538 | * @param message 错误消息 539 | * @param clue1 线索1 540 | */ 541 | public static void notEmpty(T[] array, String message, Object clue1) { 542 | if (array == null || array.length == 0) { 543 | throw new IllegalStateException(MF.m(message, clue1)); 544 | } 545 | } 546 | 547 | /** 548 | * 不能为空 549 | * 550 | * @param array array 551 | * @param message 错误消息 552 | * @param clue1 线索1 553 | * @param clue2 线索2 554 | */ 555 | public static void notEmpty(T[] array, String message, Object clue1, Object clue2) { 556 | if (array == null || array.length == 0) { 557 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 558 | } 559 | } 560 | 561 | /** 562 | * 不能为空 563 | * 564 | * @param array array 565 | * @param message 错误消息 566 | * @param clue1 线索1 567 | * @param clue2 线索2 568 | * @param clue3 线索3 569 | */ 570 | public static void notEmpty(T[] array, String message, Object clue1, Object clue2, Object clue3) { 571 | if (array == null || array.length == 0) { 572 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 573 | } 574 | } 575 | 576 | /** 577 | * 是否相等 578 | * 579 | * @param value1 value1 580 | * @param value2 value2 581 | * @param message 错误消息 582 | */ 583 | public static void equal(T value1, T value2, String message) { 584 | if (value1 == value2) { 585 | return; 586 | } 587 | if (value1 != null) { 588 | if (!value1.equals(value2)) { 589 | throw new IllegalArgumentException(message); 590 | } 591 | } else { 592 | throw new IllegalArgumentException(message); 593 | } 594 | } 595 | 596 | /** 597 | * 是否相等 598 | * 599 | * @param value1 value1 600 | * @param value2 value2 601 | * @param message 错误消息 602 | * @param clue1 线索1 603 | */ 604 | public static void equal(T value1, T value2, String message, Object clue1) { 605 | if (value1 == value2) { 606 | return; 607 | } 608 | if (value1 != null) { 609 | if (!value1.equals(value2)) { 610 | throw new IllegalStateException(MF.m(message, clue1)); 611 | } 612 | } else { 613 | throw new IllegalStateException(MF.m(message, clue1)); 614 | } 615 | } 616 | 617 | /** 618 | * 是否相等 619 | * 620 | * @param value1 value1 621 | * @param value2 value2 622 | * @param message 错误消息 623 | * @param clue1 线索1 624 | * @param clue2 线索2 625 | */ 626 | public static void equal(T value1, T value2, String message, Object clue1, Object clue2) { 627 | if (value1 == value2) { 628 | return; 629 | } 630 | if (value1 != null) { 631 | if (!value1.equals(value2)) { 632 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 633 | } 634 | } else { 635 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 636 | } 637 | } 638 | 639 | /** 640 | * @param value1 value1 641 | * @param value2 value2 642 | * @param message 错误消息 643 | * @param clue1 线索1 644 | * @param clue2 线索2 645 | * @param clue3 线索3 646 | */ 647 | public static void equal(T value1, T value2, String message, Object clue1, Object clue2, Object clue3) { 648 | if (value1 == value2) { 649 | return; 650 | } 651 | if (value1 != null) { 652 | if (!value1.equals(value2)) { 653 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 654 | } 655 | } else { 656 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 657 | } 658 | } 659 | 660 | /** 661 | * 指定有N项数据 662 | * 663 | * @param list list 664 | * @param n n 665 | * @param message 错误消息 666 | */ 667 | public static void hasN(List list, long n, String message) { 668 | 669 | if (list == null) { 670 | throw new IllegalArgumentException(message); 671 | } 672 | 673 | if (list.size() != n) { 674 | throw new IllegalArgumentException(message); 675 | } 676 | } 677 | 678 | /** 679 | * 指定有N项数据 680 | * 681 | * @param list list 682 | * @param n n 683 | * @param message 错误消息 684 | * @param clue1 线索1 685 | */ 686 | public static void hasN(List list, long n, String message, Object clue1) { 687 | 688 | if (list == null) { 689 | throw new IllegalStateException(MF.m(message, clue1)); 690 | } 691 | 692 | if (list.size() != n) { 693 | throw new IllegalStateException(MF.m(message, clue1)); 694 | } 695 | } 696 | 697 | /** 698 | * 指定有N项数据 699 | * 700 | * @param list list 701 | * @param n n 702 | * @param message 错误消息 703 | * @param clue1 线索1 704 | * @param clue2 线索2 705 | */ 706 | public static void hasN(List list, long n, String message, Object clue1, Object clue2) { 707 | 708 | if (list == null) { 709 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 710 | } 711 | 712 | if (list.size() != n) { 713 | throw new IllegalStateException(MF.m(message, clue1, clue2)); 714 | } 715 | } 716 | 717 | /** 718 | * 指定有N项数据 719 | * 720 | * @param list list 721 | * @param n n 722 | * @param message 错误消息 723 | * @param clue1 线索1 724 | * @param clue2 线索2 725 | * @param clue3 线索3 726 | */ 727 | public static void hasN(List list, long n, String message, Object clue1, Object clue2, Object clue3) { 728 | 729 | if (list == null) { 730 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 731 | } 732 | 733 | if (list.size() != n) { 734 | throw new IllegalStateException(MF.m(message, clue1, clue2, clue3)); 735 | } 736 | } 737 | 738 | /** 739 | * 必须用end结尾 740 | * 741 | * @param value 742 | * @param end 743 | * @return 744 | */ 745 | public static void mustEndWith(String value, String end) { 746 | Assert.mustNotBlank(value, "value is blank"); 747 | Assert.mustNotBlank(end, "end is blank"); 748 | 749 | if(!value.endsWith(end)){ 750 | throw new IllegalStateException(MF.m("{} must end with end{}", value, end)); 751 | } 752 | } 753 | 754 | /** 755 | * 必须用start 开始 756 | * 757 | * @param value 758 | * @param start 759 | * @return 760 | */ 761 | public static void mustStartWith(String value, String start) { 762 | Assert.mustNotBlank(value, "value is blank"); 763 | Assert.mustNotBlank(start, "end is blank"); 764 | 765 | if(!value.startsWith(start)){ 766 | throw new IllegalStateException(MF.m("{} must end with start{}", value, start)); 767 | } 768 | } 769 | 770 | } 771 | -------------------------------------------------------------------------------- /src/com/csdndownload/utils/CastUtils.java: -------------------------------------------------------------------------------- 1 | package com.csdndownload.utils; 2 | 3 | import com.sunday.commons.utils.string.JsonUtils; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * 类转换工具 10 | * 11 | * @author zhudesheng 12 | * @version 1.0 13 | * @date 2022/8/31 2:42 PM 14 | */ 15 | public class CastUtils { 16 | 17 | /** 18 | * 安全的ob转为List 19 | * 20 | * @param obj 待转换对象 21 | * @param 目录类型 22 | * @return list 23 | */ 24 | public static List objToList(Object obj, Class tClass) { 25 | if (obj == null || tClass == null) { 26 | return null; 27 | } 28 | if (obj instanceof List) { 29 | List list = (List) obj; 30 | if (CollectionUtils.isEmpty(list)) { 31 | return new ArrayList<>(); 32 | } 33 | List result = new ArrayList<>(); 34 | for (Object item : list) { 35 | if (tClass.isInstance(item)) { 36 | T cast = tClass.cast(item); 37 | result.add(cast); 38 | } 39 | } 40 | return result; 41 | } else { 42 | return null; 43 | } 44 | } 45 | 46 | /** 47 | * 安全的对象转目标类对象 48 | * @param obj 待转换对象 49 | * @param tClass 目录类型 50 | * @return T 51 | * @param 52 | */ 53 | public static T objToObj(Object obj,Class tClass){ 54 | if (obj == null || tClass == null) { 55 | return null; 56 | } 57 | if(tClass.isInstance(obj)){ 58 | return tClass.cast(obj); 59 | } 60 | if(obj instanceof String){ 61 | return JsonUtils.parseObject((String) obj,tClass); 62 | } 63 | return null; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/com/csdndownload/utils/CollectionUtils.java: -------------------------------------------------------------------------------- 1 | package com.csdndownload.utils; 2 | 3 | import java.util.*; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | import java.util.function.BiPredicate; 6 | import java.util.function.Function; 7 | import java.util.function.Predicate; 8 | import java.util.stream.Collectors; 9 | 10 | public class CollectionUtils { 11 | 12 | 13 | /** 14 | * 是否为空 15 | * 16 | * @param collection collection 17 | * @return boolean 18 | */ 19 | public static boolean isEmpty(Collection collection) { 20 | return (collection == null || collection.isEmpty()); 21 | } 22 | 23 | /** 24 | * 是否为空 25 | * 26 | * @param map map 27 | * @return boolean 28 | */ 29 | public static boolean isEmpty(Map map) { 30 | return (map == null || map.isEmpty()); 31 | } 32 | 33 | /** 34 | * 是否为空 35 | * 36 | * @param array 数组 37 | * @param 泛型 38 | * @return 是否为空 39 | */ 40 | public static boolean isEmpty(T[] array) { 41 | return (array == null || array.length == 0); 42 | } 43 | 44 | /** 45 | * 是否不为空 46 | * 47 | * @param collection 集合 48 | * @return 是否为空 49 | */ 50 | public static boolean isNotEmpty(Collection collection) { 51 | return (collection != null && !collection.isEmpty()); 52 | } 53 | 54 | /** 55 | * 是否不为空 56 | * 57 | * @param map map 58 | * @return 是否不为空 59 | */ 60 | public static boolean isNotEmpty(Map map) { 61 | return (map != null && !map.isEmpty()); 62 | } 63 | 64 | /** 65 | * 是否不为空 66 | * 67 | * @param array 数组 68 | * @param 泛型 69 | * @return 是否不为空 70 | */ 71 | public static boolean isNotEmpty(T[] array) { 72 | return (array != null && array.length > 0); 73 | } 74 | 75 | /** 76 | * 对列表进行过滤 77 | * 78 | * @param list 列表 79 | * @param predicate 如果返回true,那么将被返回 80 | * @param 数据类型 81 | * @return 新的列表 82 | */ 83 | public static List filterList(List list, Predicate predicate) { 84 | Assert.notNull(predicate, "predicate is null"); 85 | if (CollectionUtils.isEmpty(list)) { 86 | return new ArrayList<>(); 87 | } 88 | return list.stream().filter(predicate).collect(Collectors.toList()); 89 | } 90 | 91 | /** 92 | * 快速检查数据中是否有存在重复记录 93 | * 94 | * @param list 95 | * @param predicate 96 | * @param 97 | * @return 98 | */ 99 | public static boolean isUniqueList(List list, BiPredicate predicate) { 100 | if (isNotEmpty(list)) { 101 | List result = new ArrayList<>(); 102 | int valueIndex = 0; 103 | for (T value : list) { 104 | 105 | int innerIndex = 0; 106 | for (T inner : list) { 107 | 108 | if (innerIndex <= valueIndex) { 109 | innerIndex++; 110 | continue; 111 | } 112 | // 避免自己和自己比 113 | if (predicate.test(value, inner)) { 114 | return false; 115 | } 116 | innerIndex++; 117 | } 118 | valueIndex++; 119 | } 120 | return true; 121 | } else { 122 | return true; 123 | } 124 | } 125 | 126 | /** 127 | * 列表去重 128 | *

129 | * 更具对象的equal方法进行判定是否重复 130 | * 131 | * @param list 132 | * @return 133 | */ 134 | public static List uniqueList(List list) { 135 | if (isNotEmpty(list)) { 136 | return list.stream().distinct().collect(Collectors.toList()); 137 | } else { 138 | return list; 139 | } 140 | } 141 | 142 | /** 143 | * 对列表进行去重 144 | * 145 | * @param list 146 | * @param predicate 如果两个数据相同,返回true 147 | * @param 148 | * @return 149 | */ 150 | public static List uniqueList(List list, BiPredicate predicate) { 151 | if (isNotEmpty(list)) { 152 | List result = new ArrayList<>(); 153 | for (T value : list) { 154 | boolean existed = false; 155 | 156 | for (T inner : result) { 157 | // 避免自己和自己比 158 | if (value != inner && predicate.test(value, inner)) { 159 | existed = true; 160 | break; 161 | } 162 | } 163 | if (!existed) { 164 | result.add(value); 165 | } 166 | } 167 | return result; 168 | } else { 169 | return list; 170 | } 171 | } 172 | 173 | /** 174 | * 找出list1 和list2中公共的元素 175 | * 176 | * @param list1 177 | * @param list2 178 | * @param 179 | * @return 180 | */ 181 | public static List commonList(List list1, List list2) { 182 | List result = new ArrayList<>(); 183 | if (isEmpty(list1) || isEmpty(list2)) { 184 | return result; 185 | } 186 | list1.forEach((value) -> { 187 | if (list2.contains(value)) { 188 | result.add(value); 189 | } 190 | }); 191 | 192 | return result; 193 | } 194 | /** 195 | * 找出list1 和list2中公共的元素 196 | * 197 | * @param list1 198 | * @param list2 199 | * @param 200 | * @return 201 | */ 202 | public static Set commonList(Set list1, List list2){ 203 | 204 | Set result = new HashSet<>(); 205 | if (isEmpty(list1) || isEmpty(list2)) { 206 | return result; 207 | } 208 | list1.forEach((value) -> { 209 | if (list2.contains(value)) { 210 | result.add(value); 211 | } 212 | }); 213 | 214 | return result; 215 | } 216 | 217 | 218 | /** 219 | * 将相同的字段对象,映射为同一对象列表, 220 | * [{"aa":"a","bb":"b"},{"aa":"a","bb":"bb"}] 221 | * || 222 | * V 223 | * {"a":[{"aa":"a","bb":"b"},{"aa":"a","bb":"bb"}]} 224 | * 225 | * @param list 目标数据 226 | * @param function 计算字段的函数, 227 | * @param 泛型,归纳字段 228 | * @param 目标对象 229 | * @return 同一字段相同的,map映射 230 | * @warning 目标字段为null,数据将被抛弃 231 | */ 232 | public static Map> mapSameFieldToListMap(List list, Function function) { 233 | Map> result = new HashMap<>(); 234 | if (isEmpty(list)) { 235 | return result; 236 | } 237 | 238 | list.forEach((value) -> { 239 | S key = function.apply(value); 240 | if (key == null) { 241 | return; 242 | } 243 | 244 | List tList = result.get(key); 245 | if (tList == null) { 246 | tList = new ArrayList<>(); 247 | tList.add(value); 248 | result.put(key, tList); 249 | } else { 250 | tList.add(value); 251 | } 252 | }); 253 | 254 | return result; 255 | } 256 | 257 | /** 258 | * 将相同的字段对象,映射为同一对象列表, (并行版本,会打乱顺序) 259 | * [{"aa":"a","bb":"b"},{"aa":"a","bb":"bb"}] 260 | * || 261 | * V 262 | * {"a":[{"aa":"a","bb":"b"},{"aa":"a","bb":"bb"}]} 263 | * 264 | * @param list 目标数据 265 | * @param function 计算字段的函数, 266 | * @param 泛型,归纳字段 267 | * @param 目标对象 268 | * @return 同一字段相同的,map映射 269 | * @warning 目标字段为null,数据将被抛弃 270 | */ 271 | public static Map> mapSameFieldToListMapParallel(final List list, Function function) { 272 | Map> result = new ConcurrentHashMap<>(); 273 | if (isEmpty(list)) { 274 | return result; 275 | } 276 | 277 | list.parallelStream().forEach((value) -> { 278 | S key = function.apply(value); 279 | if (key == null) { 280 | return; 281 | } 282 | 283 | List tList = result.get(key); 284 | if (tList == null) { 285 | synchronized (list){ 286 | tList = result.get(key); 287 | if(tList == null){ 288 | tList = Collections.synchronizedList(new ArrayList<>()); 289 | } 290 | tList.add(value); 291 | result.put(key, tList); 292 | } 293 | } else { 294 | tList.add(value); 295 | } 296 | }); 297 | return result; 298 | } 299 | 300 | 301 | /** 302 | * 对象列表映射为另外一个类型的列表,重复数据将被去掉 303 | * 304 | * @param list 数据列表 305 | * @param function 映射函数 306 | * @param 原 307 | * @param 目标 308 | * @return 映射后数据列表 309 | */ 310 | public static List mapToList(List list, Function function) { 311 | if (isEmpty(list)) { 312 | return new ArrayList<>(); 313 | } 314 | return list.stream().map(function).distinct().collect(Collectors.toList()); 315 | } 316 | 317 | 318 | /** 319 | * 对象列表映射为另外一个类型的列表,重复数据将被去掉 (并行版本,会打乱顺序) 320 | * 321 | * @param list 数据列表 322 | * @param function 映射函数 323 | * @param 原 324 | * @param 目标 325 | * @return 映射后数据列表 326 | */ 327 | public static List mapToListParallel(List list, Function function) { 328 | if (isEmpty(list)) { 329 | return new ArrayList<>(); 330 | } 331 | return list.parallelStream().map(function).distinct().collect(Collectors.toList()); 332 | } 333 | 334 | 335 | /** 336 | * 对象列表映射为另外一个类型的集合 337 | * 338 | * @param list 数据列表 339 | * @param function 映射函数 340 | * @param 原 341 | * @param 目标 342 | * @return 映射后数据集合 343 | */ 344 | public static Set mapToSet(List list, Function function) { 345 | if (isEmpty(list)) { 346 | return new HashSet<>(); 347 | } 348 | return list.stream().map(function).collect(Collectors.toSet()); 349 | } 350 | 351 | /** 352 | * 对象列表映射为另外一个类型的集合 (并行版本,会打乱顺序) 353 | * 354 | * @param list 数据列表 355 | * @param function 映射函数 356 | * @param 原 357 | * @param 目标 358 | * @return 映射后数据集合 359 | */ 360 | public static Set mapToSetParallel(List list, Function function) { 361 | if (isEmpty(list)) { 362 | return new HashSet<>(); 363 | } 364 | return list.parallelStream().map(function).collect(Collectors.toSet()); 365 | } 366 | 367 | 368 | /** 369 | * 对象列表映射为一个map 370 | * 371 | * @param list 数据列表 372 | * @param kFunction 获取map key的函数 373 | * @param vFunction 获取map value的函数 374 | * @param 原数据 375 | * @param key 376 | * @param value 377 | * @return 映射后数据map 378 | */ 379 | public static Map mapToMap(List list, Function kFunction, Function vFunction) { 380 | if (isEmpty(list)) { 381 | return new HashMap<>(); 382 | } 383 | Map result = new HashMap<>(); 384 | list.forEach((value) -> { 385 | K key = kFunction.apply(value); 386 | 387 | V v = result.get(key); 388 | if (v == null) { 389 | result.put(key, vFunction.apply(value)); 390 | } 391 | }); 392 | return result; 393 | } 394 | 395 | /** 396 | * 对象列表映射为一个map (并行版本,会打乱顺序) 397 | * 398 | * @param list 数据列表 399 | * @param kFunction 获取map key的函数 400 | * @param vFunction 获取map value的函数 401 | * @param 原数据 402 | * @param key 403 | * @param value 404 | * @return 映射后数据map 405 | */ 406 | public static Map mapToMapParallel(final List list, Function kFunction, Function vFunction) { 407 | Map result = new ConcurrentHashMap<>(); 408 | 409 | if (isEmpty(list)) { 410 | return result; 411 | } 412 | 413 | list.parallelStream().forEach((value) -> { 414 | K key = kFunction.apply(value); 415 | 416 | V v = result.get(key); 417 | if (v == null) { 418 | synchronized (list){ 419 | v = result.get(key); 420 | if(v == null){ 421 | result.put(key, vFunction.apply(value)); 422 | } 423 | } 424 | } 425 | }); 426 | return result; 427 | } 428 | 429 | /** 430 | * 从一个列表中对象中,抽出一个字段列表,并去重 431 | * 432 | * @param list 列表数据 433 | * @param function 取字段函数 434 | * @param 字段类型 435 | * @param 数据类型 436 | * @return 字段列表 437 | */ 438 | public static List mapGetSameFieldUniqueList(List list, Function function) { 439 | List result = new ArrayList<>(); 440 | if (isEmpty(list)) { 441 | return result; 442 | } 443 | result.addAll(list.stream().map(function).filter(Objects::nonNull).distinct().collect(Collectors.toList())); 444 | 445 | return result; 446 | } 447 | 448 | 449 | /** 450 | * 从一个列表中对象中,抽出一个字段列表,并去重 (并行版本,会打乱顺序) 451 | * 452 | * @param list 列表数据 453 | * @param function 取字段函数 454 | * @param 字段类型 455 | * @param 数据类型 456 | * @return 字段列表 457 | */ 458 | public static List mapGetSameFieldUniqueListParallel(List list, Function function) { 459 | List result = new ArrayList<>(); 460 | if (isEmpty(list)) { 461 | return result; 462 | } 463 | result.addAll(list.parallelStream().map(function).filter(Objects::nonNull).distinct().collect(Collectors.toList())); 464 | 465 | return result; 466 | } 467 | 468 | 469 | /** 470 | * 从一个列表中对象中,抽出一个字段列表,并去重 471 | * 472 | * @param list 列表数据 473 | * @param function 取字段函数 474 | * @param uniquePredicate 判断唯一函数 475 | * @param 字段类型 476 | * @param 数据类型 477 | * @return 字段列表 478 | */ 479 | public static List mapGetSameFieldUniqueList(List list, Function function, BiPredicate uniquePredicate) { 480 | List result = new ArrayList<>(); 481 | if (isEmpty(list)) { 482 | return result; 483 | } 484 | result.addAll(list.stream().map(function).filter(Objects::nonNull).collect(Collectors.toList())); 485 | 486 | return uniqueList(result, uniquePredicate); 487 | } 488 | 489 | 490 | /** 491 | * 从一个列表中对象中,抽出一个字段列表,并去重 (并行版本,会打乱顺序) 492 | * 493 | * @param list 列表数据 494 | * @param function 取字段函数 495 | * @param uniquePredicate 判断唯一函数 496 | * @param 字段类型 497 | * @param 数据类型 498 | * @return 字段列表 499 | */ 500 | public static List mapGetSameFieldUniqueListParallel(List list, Function function, BiPredicate uniquePredicate) { 501 | List result = new ArrayList<>(); 502 | if (isEmpty(list)) { 503 | return result; 504 | } 505 | result.addAll(list.parallelStream().map(function).filter(Objects::nonNull).collect(Collectors.toList())); 506 | 507 | return uniqueList(result, uniquePredicate); 508 | } 509 | 510 | /** 511 | * 将list1 减去list2中的元素,得到的列表,可能为空 512 | * 513 | * @param list1 被减数 将不会改变 514 | * @param list2 减数 将不会改变 515 | * @param 516 | * @return list1 - list2 之后的剩余 517 | */ 518 | public static List subtractList(List list1, List list2) { 519 | List result = new ArrayList<>(); 520 | 521 | if (isEmpty(list1)) { 522 | return result; 523 | } 524 | if (isEmpty(list2)) { 525 | return list1; 526 | } 527 | result.addAll(list1); 528 | result.removeAll(list2); 529 | return result; 530 | } 531 | 532 | /** 533 | * 将list1 减去list2中的元素,得到的列表,可能为空 534 | * 535 | * @param list1 被减数 将不会改变 536 | * @param list2 减数 将不会改变 537 | * @param 538 | * @return list1 - list2 之后的剩余 539 | */ 540 | public static Set subtractList(Set list1, Set list2) { 541 | Set result = new HashSet<>(); 542 | 543 | if (isEmpty(list1)) { 544 | return result; 545 | } 546 | if (isEmpty(list2)) { 547 | return list1; 548 | } 549 | result.addAll(list1); 550 | result.removeAll(list2); 551 | return result; 552 | } 553 | 554 | 555 | /** 556 | * 合并列表,如果有重复的,最终的结果将会去重 557 | * 558 | * @param list 559 | * @param list2 560 | * @param 561 | * @return 562 | */ 563 | @SafeVarargs 564 | public static List mergeList(List list, List... list2) { 565 | Assert.notNull(list, "list is null"); 566 | Assert.notNull(list2, "list2 is null"); 567 | 568 | List result = new ArrayList<>(list); 569 | if (list2.length > 0) { 570 | for (List ts : list2) { 571 | result.addAll(ts); 572 | } 573 | return uniqueList(result); 574 | } else { 575 | return list; 576 | } 577 | } 578 | 579 | /** 580 | * 合并列表,如果有重复的,最终的结果将会去重 581 | * @param list 582 | * @param list2 583 | * @return 584 | * @param 585 | */ 586 | @SafeVarargs 587 | public static List mergeList(T[] list,T[]... list2){ 588 | 589 | List result = new ArrayList<>(); 590 | 591 | if(list != null && list.length != 0){ 592 | result.addAll(CollectionUtils.ofList(list)); 593 | } 594 | 595 | if(list2.length > 0){ 596 | for (T[] tmpList : list2) { 597 | 598 | if(tmpList != null && tmpList.length != 0){ 599 | result.addAll(CollectionUtils.ofList(tmpList)); 600 | } 601 | } 602 | } 603 | return uniqueList(result); 604 | } 605 | 606 | 607 | 608 | /** 609 | * 取列表中的第一个 610 | * 611 | * @param list 列表数据 612 | * @param 泛型 613 | * @return 值 614 | */ 615 | public static T first(List list) { 616 | if (isEmpty(list)) { 617 | return null; 618 | } 619 | return list.get(0); 620 | } 621 | 622 | /** 623 | * 取列表中的第一个 624 | * 625 | * @param list 列表数据 626 | * @param 泛型 627 | * @return 值 628 | */ 629 | public static T first(T[] list) { 630 | if (isEmpty(list)) { 631 | return null; 632 | } 633 | return list[0]; 634 | } 635 | 636 | /** 637 | * 快速列表列表 638 | * 639 | * @param data 数据数组 640 | * @param 数据类型 641 | * @return 列表 642 | */ 643 | public static List ofList(T... data) { 644 | List result = new ArrayList<>(); 645 | if (data.length > 0) { 646 | for (int i = 0; i < data.length; i++) { 647 | result.add(data[i]); 648 | } 649 | } 650 | return result; 651 | } 652 | 653 | /** 654 | * 快速列表列表 655 | * 656 | * @param data 数据数组 657 | * @param 数据类型 658 | * @return 列表 659 | */ 660 | public static List ofList(Collection data) { 661 | List result = new ArrayList<>(); 662 | if (data != null && data.size() > 0) { 663 | result.addAll(data); 664 | } 665 | return result; 666 | } 667 | 668 | /** 669 | * 快速set 670 | * 671 | * @param data 数据 672 | * @param 泛型 673 | * @return 集合 674 | */ 675 | public static Set ofSet(T... data) { 676 | Set result = new HashSet<>(); 677 | if (data.length > 0) { 678 | for (int i = 0; i < data.length; i++) { 679 | result.add(data[i]); 680 | } 681 | } 682 | return result; 683 | } 684 | 685 | /** 686 | * 快速set 687 | * 688 | * @param data 数据 689 | * @param 泛型 690 | * @return 集合 691 | */ 692 | public static Set ofSet(Collection data) { 693 | Set result = new HashSet<>(); 694 | if (data != null && data.size() > 0) { 695 | result.addAll(data); 696 | } 697 | return result; 698 | } 699 | 700 | /** 701 | * 反向list 最后的成员放在最前面 702 | * 703 | * @param list 704 | * @param 705 | * @return 706 | */ 707 | public static List revert(List list) { 708 | List result = new ArrayList<>(); 709 | 710 | if (isNotEmpty(list)) { 711 | for (int i = list.size() - 1; i > -1; i--) { 712 | result.add(list.get(i)); 713 | } 714 | } 715 | return result; 716 | } 717 | 718 | 719 | } 720 | --------------------------------------------------------------------------------