├── .gitignore ├── .npmrc ├── LICENSE ├── README.md ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── main │ ├── Algorithms.ts │ ├── Booleans.ts │ ├── Collectors.ts │ ├── Collects.ts │ ├── Comparators.ts │ ├── Dates.ts │ ├── Delegatables.ts │ ├── Emptys.ts │ ├── Exceptions.ts │ ├── Formatters.ts │ ├── Functions.ts │ ├── HashCodes.ts │ ├── Iterables.ts │ ├── Numbers.ts │ ├── Objects.ts │ ├── Pipeline.ts │ ├── Preconditions.ts │ ├── Strings.ts │ ├── Types.ts │ ├── index.ts │ ├── lodash.ts │ └── logger.ts └── test │ └── ts │ ├── Collects.test.ts │ ├── Empty.test.ts │ ├── List.test.ts │ ├── Map.test.ts │ ├── Objects.test.ts │ ├── Set.test.ts │ └── Types.test.ts ├── tsconfig.cjs.json ├── tsconfig.esm.json ├── tsconfig.json ├── tsconfig.types.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | dist 4 | node_modules 5 | target 6 | src/test/result -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bes2008/langx-js/f0ef31d8c2a5977c082388ca7be72865b963d81b/.npmrc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JavaScript language extensions, a replacement or a supplement of the lodash. Write JavaScript using Java API for a javaer, javascripter, typescripter. 2 | 3 | 4 | ## Versions 5 | [![npm](https://img.shields.io/badge/npm-v1.1.0-green.svg)](https://www.npmjs.com/package/langx-js/v/1.1.0) 6 | [![npm](https://img.shields.io/badge/npm-v1.0.7-green.svg)](https://www.npmjs.com/package/langx-js/v/1.0.7) 7 | 8 | ## Overwrite lodash 9 | 1. Array utilities 10 | 11 | ## Migrate [Java API](https://docs.oracle.com/javase/7/docs/api/) 12 | 13 | All java collection written in Iterables.ts module 14 | 15 | |TypeScript Class or Module | Java Class | 16 | |-----------------|---------------------| 17 | |Collection |java.util.Collection | 18 | |List |java.util.List | 19 | |ArrayList |java.util.ArrayList | 20 | |LinkedList |java.util.LinkedList | 21 | |LikeJavaSet |java.util.Set | 22 | |LikeJavaMap |java.util.Map | 23 | |HashSet|java.util.HashSet| 24 | |LinkedHashSet|java.util.LinkedHashSet| 25 | |TreeSet|java.util.TreeSet| 26 | |HashMap|java.util.HashMap| 27 | |LinkedHashMap|java.util.LinkedHashMap| 28 | |TreeMap|java.util.TreeMap| 29 | |logger |Logger | 30 | |Exceptions| some java.lang.RuntimeException (s)| 31 | 32 | 33 | ## Migrate [langx-java](https://github.com/fangjinuo/langx-java) Utilities 34 | |TypeScript Class or Module | langx-java Class | 35 | |-----------------|---------------------| 36 | |Emptys |Emptys | 37 | |Objects |Objects | 38 | |Numbers| Numbers| 39 | |Booleans| Booleans| 40 | |Dates| Dates| 41 | |Preconditions |Preconditions | 42 | |Collects |Collects | 43 | |Functions| Function,Consumer,Predicate,Supplier ... | 44 | |Pipeline|Pipeline [Like Java8 Stream API ]| 45 | 46 | 47 | ## References 48 | + [JavaScript API](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript) 49 | + [W3School 中文站](https://www.w3cschool.cn/) 50 | + [TypeScript docs](http://www.typescriptlang.org/docs/handbook/basic-types.html) | [TypeScript 中文文档](http://bigsec.net/b52/typescript-handbook/) 51 | + [NPM docs](https://docs.npmjs.com/cli-documentation/) | [NPM 中文文档](https://www.npmjs.cn/) 52 | + [Webpack docs](https://webpack.js.org/) | [Webpack 中文文档](https://www.webpackjs.com/concepts/) 53 | + [Babel docs](https://babeljs.io/docs/en/) | [Babel 中文文档](https://www.babeljs.cn/docs/) 54 | + [Jest](https://jestjs.io/) | [Jest 快速访问站点](https://www.w3cschool.cn/doc_jest/) 55 | + [Node.js Debugging Guide](https://nodejs.org/en/docs/guides/debugging-getting-started/) | [Jest TypeScript Debugging Guide](https://www.cnblogs.com/f1194361820/p/12497298.html) 56 | 57 | ## [推广](https://github.com/fangjinuo) 58 | + langx 系列 59 | - [langx-js](https://github.com/fangjinuo/langx-js):TypeScript, JavaScript tools 60 | - [langx-java](https://github.com/fangjinuo/langx-java): Java tools ,可以替换guava, apache commons-lang,io, hu-tool等 61 | + [easyjson](https://github.com/fangjinuo/easyjson): 一个通用的JSON库门面,可以无缝的在各个JSON库之间切换,就像slf4j那样。 62 | + [sqlhelper](https://github.com/fangjinuo/sqlhelper): SQL工具套件(通用分页、DDL Dump、SQLParser、URL Parser、批量操作工具等)。 63 | + [esmvc](https://github.com/fangjinuo/es-mvc): ElasticSearch 通用客户端,就像MyBatis Mapper那样顺滑 64 | + [redisclient](https://github.com/fangjinuo/redisclient): 基于Spring RestTemplate提供的客户端 65 | + [audit](https://github.com/fangjinuo/audit):通用的Java应用审计框架 66 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports= { 2 | "automock": false, 3 | "browser": true, 4 | "bail": true, 5 | "cacheDirectory": "/src/test/result/cache", 6 | "collectCoverage": true, 7 | "collectCoverageFrom": ["/src/main"], 8 | "coverageDirectory": "/src/test/result/coverage", 9 | "coverageReporters": ["json"], 10 | "moduleFileExtensions": ["js", "jsx", "json", "ts", "tsx"], 11 | "notify": true, 12 | "clearMocks": true, 13 | "roots":["/src/test/ts/"], 14 | "transform": { 15 | "^.+\\.tsx?$": "ts-jest" 16 | } 17 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "langx-js", 3 | "version": "1.1.0", 4 | "description": "JavaScript language extensions, a replacement or a supplement of the lodash", 5 | "keywords": [ 6 | "lodash", 7 | "JavaScript", 8 | "TypeScript", 9 | "Java", 10 | "Stream API", 11 | "Collection", 12 | "ArrayList", 13 | "LinkedList", 14 | "HashSet", 15 | "TreeSet", 16 | "LinkedHashSet", 17 | "HashMap", 18 | "TreeMap", 19 | "LinkedHashMap" 20 | ], 21 | "authors": [ 22 | { 23 | "name": "jinuo.fang", 24 | "email": "fs1194361820@163.com", 25 | "url": "https://github.com/fangjinuo" 26 | }, 27 | { 28 | "name": "wckgo", 29 | "email": "wckgogogo@gmail.com", 30 | "url": "https://github.com/wckgo" 31 | } 32 | ], 33 | "main": "./dist/cjs/index.js", 34 | "module": "./dist/esm/index.js", 35 | "types": "./dist/types/index.d.ts", 36 | "scripts": { 37 | "compile": "tsc -b ./tsconfig.cjs.json ./tsconfig.esm.json ./tsconfig.types.json ", 38 | "build:clean": "shx rm -rf ./dist", 39 | "build:package": "npm install && npm-run-all build:clean compile", 40 | "publish": "npm run build:package && npm publish", 41 | "test": "jest", 42 | "debug": "node --inspect ./node_modules/jest/bin/jest --runInBand --watch" 43 | }, 44 | "license": "Apache-2.0", 45 | "licenses": [ 46 | { 47 | "type": "Apache-2.0", 48 | "url": "https://github.com/fangjinuo/langx-js/blob/master/LICENSE" 49 | } 50 | ], 51 | "homepage": "https://github.com/fangjinuo/langx-js", 52 | "repository": { 53 | "type": "git", 54 | "url": "https://github.com/fangjinuo/langx-js.git" 55 | }, 56 | "peerDependencies": {}, 57 | "devDependencies": { 58 | "npm-run-all": "^4.1.5", 59 | "shx": "^0.3.2", 60 | "typescript": "^3.8.3", 61 | "jest": ">=25 <26", 62 | "@types/jest": "^25.1.0", 63 | "ts-jest": "^25.2.1", 64 | "@types/node": "^13.9.1" 65 | }, 66 | "files": [ 67 | "package.json", 68 | "README", 69 | "LICENSE", 70 | "dist/**/*.d.ts", 71 | "dist/**/*.js" 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /src/main/Algorithms.ts: -------------------------------------------------------------------------------- 1 | import {Comparator} from "./Comparators"; 2 | import * as Emptys from "./Emptys"; 3 | import {ArrayList} from "./Iterables"; 4 | 5 | 6 | /** 7 | * if value== null: not found, the index is the suitable index 8 | * if value !=null: found, the index is the matched value's index 9 | */ 10 | export class SearchResult { 11 | value: E; 12 | index: number; 13 | 14 | constructor(index: number, value: E) { 15 | this.index = index; 16 | this.value = value; 17 | } 18 | } 19 | 20 | /** 21 | * using binary search logic to search an element 22 | * the search scope is [fromIndex, toIndex] 23 | * @param sortedArray the sorted array 24 | * @param fromIndex 25 | * @param toIndex 26 | * @param e the value will to search 27 | * @param asc search from left to right if true, else search from right to left 28 | * @param comparator 29 | */ 30 | export function binarySearch(sortedArray: ArrayList, e: any, comparator: Comparator, asc?: boolean, fromIndex?: number, toIndex?: number): SearchResult { 31 | if (Emptys.isEmpty(sortedArray)) { 32 | return new SearchResult(0, null); 33 | } 34 | if (fromIndex == null || fromIndex < 0) { 35 | fromIndex = 0; 36 | } 37 | if (toIndex == null || toIndex >= sortedArray.size()) { 38 | toIndex = sortedArray.size() - 1; 39 | } 40 | asc = asc == null || asc; 41 | 42 | if (asc) { 43 | // compare the first of current scope 44 | let cFirst = comparator.compare(e, sortedArray.get(fromIndex)); 45 | if (cFirst <= 0) { 46 | return new SearchResult(fromIndex, cFirst == 0 ? sortedArray.get(fromIndex) : null); 47 | } 48 | 49 | if (fromIndex == toIndex) { 50 | return new SearchResult(toIndex + 1, null); 51 | } 52 | 53 | // compare the last of current scope 54 | let cLast = comparator.compare(e, sortedArray.get(toIndex)); 55 | if (cLast >= 0) { 56 | return new SearchResult(cLast == 0 ? toIndex : (toIndex + 1), cLast == 0 ? sortedArray.get(toIndex) : null); 57 | } 58 | if (toIndex - fromIndex == 1) { 59 | // has no middle element 60 | return new SearchResult(toIndex, null); 61 | } 62 | } else { 63 | // compare the last of current scope 64 | let cLast = comparator.compare(e, sortedArray.get(toIndex)); 65 | if (cLast >= 0) { 66 | return new SearchResult(cLast == 0 ? toIndex : (toIndex + 1), cLast == 0 ? sortedArray.get(toIndex) : null); 67 | } 68 | 69 | if (fromIndex == toIndex) { 70 | return new SearchResult(toIndex - 1, null); 71 | } 72 | 73 | // compare the first of current scope 74 | let cFirst = comparator.compare(e, sortedArray.get(fromIndex)); 75 | if (cFirst <= 0) { 76 | return new SearchResult(fromIndex, cFirst == 0 ? sortedArray.get(fromIndex) : null); 77 | } 78 | 79 | if (toIndex - fromIndex == 1) { 80 | // has no middle element 81 | return new SearchResult(toIndex, null); 82 | } 83 | } 84 | 85 | // compare the middle of current scope 86 | let middleIndex = Math.floor((fromIndex + toIndex + 1) / 2); 87 | let cMiddle = comparator.compare(e, sortedArray.get(middleIndex)); 88 | if (cMiddle == 0) { 89 | return new SearchResult(middleIndex, sortedArray.get(middleIndex)); 90 | } 91 | if (cMiddle < 0) { 92 | // go to the left 93 | if (fromIndex + 1 >= middleIndex) { 94 | // end 95 | return new SearchResult(middleIndex, null); 96 | } 97 | return binarySearch(sortedArray, e, comparator, asc, fromIndex + 1, middleIndex - 1); 98 | } else { 99 | // go to the right 100 | if (toIndex - 1 <= middleIndex) { 101 | // end 102 | return new SearchResult(middleIndex + 1, null); 103 | } 104 | return binarySearch(sortedArray, e, comparator, asc, middleIndex + 1, toIndex - 1); 105 | } 106 | } -------------------------------------------------------------------------------- /src/main/Booleans.ts: -------------------------------------------------------------------------------- 1 | import * as Objects from "./Objects"; 2 | 3 | /** 4 | * Reference java Boolean's hashcode() 5 | * @param b 6 | */ 7 | export function hashCode(b: boolean) { 8 | return b ? 1231 : 1237; 9 | } 10 | 11 | export function asBoolean(obj: any): boolean { 12 | return Objects.isNotEmpty(obj); 13 | } -------------------------------------------------------------------------------- /src/main/Collectors.ts: -------------------------------------------------------------------------------- 1 | import * as Functions from "./Functions"; 2 | import * as Preconditions from "./Preconditions"; 3 | import { 4 | Consumer2, 5 | falsePredicate, IndexedConsumer2, 6 | Predicate, 7 | Predicate2, 8 | Supplier0, 9 | truePredicate 10 | } from "./Functions"; 11 | 12 | import { 13 | ArrayList, 14 | HashMap, 15 | HashSet, 16 | LikeJavaMap, 17 | LinkedHashMap, 18 | LinkedHashSet, 19 | LinkedList, List, 20 | TreeMap, 21 | TreeSet 22 | } from "./Iterables"; 23 | import * as Collects from "./Collects"; 24 | import {asIterable, newHashSet, newLinkedHashMap} from "./Collects"; 25 | import {Comparator} from "./Comparators"; 26 | import {Func} from "./Functions"; 27 | import {Func2} from "./Functions"; 28 | import * as Types from "./Types"; 29 | 30 | 31 | /** 32 | * @param C the container will be return, also te container will be fill 33 | * @param E the element in a will be iterate 34 | */ 35 | export interface Collector> { 36 | supplier(): Supplier0; 37 | 38 | accumulator(): Consumer2; 39 | 40 | consumePredicate?(): Predicate | Predicate2 | Function; 41 | 42 | breakPredicate?(): Predicate | Predicate2 | Function; 43 | } 44 | 45 | export abstract class AbstractCollector> implements Collector { 46 | consumePredicate(): Predicate | Predicate2 | Function { 47 | return truePredicate(); 48 | } 49 | 50 | breakPredicate(): Predicate | Predicate2 | Function { 51 | return falsePredicate(); 52 | } 53 | 54 | abstract supplier(): Supplier0; 55 | 56 | abstract accumulator(): Consumer2; 57 | } 58 | 59 | 60 | export function collect1(obj: object, containerFactory: Supplier0>, consumer: Consumer2, any>, consumePredicate?: Predicate | Predicate2 | Function, breakPredicate?: Predicate | Predicate2 | Function): Iterable { 61 | return collect(asIterable(obj), { 62 | accumulator(): Consumer2, any> { 63 | return consumer; 64 | }, 65 | supplier(): Supplier0> { 66 | return containerFactory; 67 | }, 68 | breakPredicate(): Predicate | Predicate2 | Function { 69 | return breakPredicate == null ? falsePredicate() : breakPredicate; 70 | }, 71 | consumePredicate(): Predicate | Predicate2 | Function { 72 | return consumePredicate == null ? truePredicate() : consumePredicate; 73 | } 74 | }); 75 | } 76 | 77 | export function collect(iterable: Iterable| undefined | null, collector: Collector>): Iterable { 78 | let collection = collector.supplier().get(); 79 | let consumer = collector.accumulator(); 80 | let consumePredicate: Predicate | Predicate2 | Function; 81 | if (Types.isFunction(collector["consumePredicate"])) { 82 | consumePredicate = (collector["consumePredicate"])(); 83 | } else { 84 | consumePredicate = truePredicate(); 85 | } 86 | 87 | let breakPredicate: Predicate | Predicate2 | Function; 88 | if (Types.isFunction(collector["breakPredicate"])) { 89 | breakPredicate = (collector["breakPredicate"])(); 90 | } else { 91 | breakPredicate = falsePredicate(); 92 | } 93 | 94 | Collects.forEach(iterable, (element) => { 95 | consumer.accept(collection, element); 96 | }, consumePredicate, breakPredicate); 97 | return collection; 98 | } 99 | 100 | export function toList(): Collector> { 101 | return toArrayList(); 102 | } 103 | 104 | export function toArrayList(): Collector> { 105 | return new class extends AbstractCollector> { 106 | accumulator(): Consumer2 { 107 | return { 108 | accept(container: ArrayList, element: any) { 109 | container.add(element); 110 | this.index++; 111 | } 112 | } 113 | } 114 | 115 | supplier(): Supplier0> { 116 | return { 117 | get(): ArrayList { 118 | return Collects.newArrayList(); 119 | } 120 | }; 121 | } 122 | 123 | } 124 | } 125 | 126 | export function toLinkedList(): Collector> { 127 | return new class extends AbstractCollector> { 128 | accumulator(): Consumer2 { 129 | return { 130 | accept(container: LinkedList, element: any) { 131 | container.add(element); 132 | } 133 | }; 134 | } 135 | 136 | supplier(): Supplier0> { 137 | return { 138 | get(): LinkedList { 139 | return Collects.newLinkedList(); 140 | } 141 | }; 142 | } 143 | 144 | } 145 | } 146 | 147 | export function toSet(): Collector, any> { 148 | return toHashSet(); 149 | } 150 | 151 | export function toHashSet(): Collector> { 152 | return new class extends AbstractCollector> { 153 | accumulator(): Consumer2, any> { 154 | return { 155 | accept(set: HashSet, element: any) { 156 | set.add(element); 157 | } 158 | }; 159 | } 160 | 161 | supplier(): Supplier0> { 162 | return { 163 | get(): HashSet { 164 | return newHashSet(); 165 | } 166 | }; 167 | } 168 | } 169 | } 170 | 171 | 172 | export function toTreeSet(comparator?: Comparator): Collector> { 173 | return new class extends AbstractCollector> { 174 | accumulator(): Consumer2, any> { 175 | return { 176 | accept(set: TreeSet, element: any) { 177 | set.add(element); 178 | } 179 | }; 180 | } 181 | 182 | supplier(): Supplier0> { 183 | return { 184 | get(): TreeSet { 185 | return Collects.newTreeSet(undefined, comparator); 186 | } 187 | }; 188 | } 189 | } 190 | } 191 | 192 | export function toLinkedHashSet(): Collector> { 193 | return new class extends AbstractCollector> { 194 | accumulator(): Consumer2, any> { 195 | return { 196 | accept(set: LinkedHashSet, element: any) { 197 | set.add(element); 198 | } 199 | }; 200 | } 201 | 202 | supplier(): Supplier0> { 203 | return { 204 | get(): LinkedHashSet { 205 | return Collects.newLinkedHashSet(undefined); 206 | } 207 | }; 208 | } 209 | } 210 | } 211 | 212 | export function toMap(keyMapper: Func | Func2 | Function, valueMapper: Func | Func2 | Function): Collector> { 213 | return toHashMap(keyMapper, valueMapper); 214 | } 215 | 216 | export function toHashMap(keyMapper: Func | Func2 | Function, valueMapper: Func | Func2 | Function): Collector> { 217 | return new class extends AbstractCollector> { 218 | accumulator(): Consumer2, any> { 219 | return new class implements IndexedConsumer2, any> { 220 | index: number = 0; 221 | 222 | accept(map: HashMap, element: any) { 223 | map.put(Functions.mappingCollectionElement(keyMapper, element, this.index), Functions.mappingCollectionElement(valueMapper, element, this.index)); 224 | this.index++; 225 | } 226 | }; 227 | } 228 | 229 | supplier(): Supplier0> { 230 | return { 231 | get(): HashMap { 232 | return Collects.newHashMap(); 233 | } 234 | }; 235 | } 236 | } 237 | } 238 | 239 | export function toLinkedHashMap(keyMapper: Func | Func2 | Function, valueMapper: Func | Func2 | Function): Collector> { 240 | return new class extends AbstractCollector> { 241 | accumulator(): Consumer2, any> { 242 | return new class implements IndexedConsumer2, any> { 243 | index: number = 0; 244 | 245 | accept(map: LinkedHashMap, element: any) { 246 | map.put(Functions.mappingCollectionElement(keyMapper, element, this.index), Functions.mappingCollectionElement(valueMapper, element, this.index)); 247 | this.index++; 248 | } 249 | }; 250 | } 251 | 252 | supplier(): Supplier0> { 253 | return { 254 | get(): LinkedHashMap { 255 | return Collects.newLinkedHashMap(); 256 | } 257 | }; 258 | } 259 | } 260 | } 261 | 262 | 263 | export function toTreeMap(keyMapper: Func | Func2 | Function, valueMapper: Func | Func2 | Function, comparator?: Comparator): Collector> { 264 | return new class extends AbstractCollector> { 265 | accumulator(): Consumer2, any> { 266 | return new class implements IndexedConsumer2, any> { 267 | index: number = 0; 268 | 269 | accept(map: TreeMap, element: any) { 270 | map.put(Functions.mappingCollectionElement(keyMapper, element, this.index), Functions.mappingCollectionElement(valueMapper, element, this.index)); 271 | this.index++; 272 | } 273 | }; 274 | } 275 | 276 | supplier(): Supplier0> { 277 | return { 278 | get(): TreeMap { 279 | return Collects.newTreeMap(undefined, comparator); 280 | } 281 | }; 282 | } 283 | } 284 | } 285 | 286 | 287 | export function groupingBy(classifier: Func | Func2 | Function, mapFactory: Supplier0>>): Collector>> { 288 | Preconditions.checkNonNull(classifier); 289 | Preconditions.checkNonNull(mapFactory); 290 | return new class extends AbstractCollector>> { 291 | accumulator(): Consumer2, any> { 292 | return new class implements IndexedConsumer2>, any> { 293 | index: number = 0; 294 | 295 | accept(map: LikeJavaMap>, element: any) { 296 | let group: any = Functions.mapping(classifier, [element]); 297 | let list: List = map.get(group); 298 | if (list == null) { 299 | list = Collects.newArrayList(); 300 | map.put(group, list); 301 | } 302 | list.add(element); 303 | this.index++; 304 | } 305 | } 306 | } 307 | 308 | supplier(): Supplier0>> { 309 | return mapFactory; 310 | } 311 | 312 | } 313 | } 314 | 315 | export function partioningBy(classifier: Func | Func2 | Function): Collector>> { 316 | return groupingBy(classifier, { 317 | get(): LikeJavaMap> { 318 | return newLinkedHashMap(); 319 | } 320 | }); 321 | } 322 | -------------------------------------------------------------------------------- /src/main/Collects.ts: -------------------------------------------------------------------------------- 1 | import * as Booleans from "./Booleans"; 2 | import * as Types from "./Types"; 3 | import * as Numbers from "./Numbers"; 4 | import * as Objects from "./Objects"; 5 | import * as Functions from "./Functions"; 6 | import * as Emptys from "./Emptys"; 7 | import { 8 | Consumer, 9 | Consumer2, 10 | ConsumerType, falsePredicate, 11 | Func, 12 | Func2, 13 | FunctionType, 14 | Predicate, 15 | Predicate2, 16 | PredicateType, truePredicate 17 | } from "./Functions"; 18 | import * as Iterables from "./Iterables"; 19 | import { 20 | AbstractCollection, 21 | AbstractList, AbstractMap, AbstractSet, 22 | ArrayList, 23 | Collection, 24 | HashMap, 25 | HashSet, 26 | LikeJavaMap, 27 | LikeJavaSet, 28 | LinearCollection, 29 | LinkedHashMap, 30 | LinkedHashSet, 31 | LinkedList, 32 | List, 33 | MapEntry, SimpleMapEntry, 34 | TreeMap, 35 | TreeSet 36 | } from "./Iterables"; 37 | import * as Preconditions from "./Preconditions"; 38 | import {Comparator, ReverseComparator} from "./Comparators"; 39 | import * as Collectors from "./Collectors"; 40 | import {partioningBy} from "./Collectors"; 41 | import {Supplier0} from "./Functions"; 42 | 43 | 44 | export function emptyArray(): Array { 45 | return []; 46 | } 47 | 48 | export function emptyList(forQuery?: any) { 49 | return Booleans.asBoolean(forQuery) ? emptyArrayList() : emptyLinkedList(); 50 | } 51 | 52 | export function emptyArrayList(): ArrayList { 53 | return new ArrayList(); 54 | } 55 | 56 | export function emptyLinkedList(): LinkedList { 57 | return new LinkedList(); 58 | } 59 | 60 | export function emptyHashSet(): HashSet { 61 | return new HashSet(); 62 | } 63 | 64 | export function emptyLinkedHashSet(): LinkedHashSet { 65 | return new LinkedHashSet(); 66 | } 67 | 68 | export function emptyTreeSet(comparator?: Comparator): TreeSet { 69 | return new TreeSet(>Objects.unknownNull(), comparator); 70 | } 71 | 72 | export function emptyLinkedHashMap(): LinkedHashMap { 73 | return new LinkedHashMap(); 74 | } 75 | 76 | export function emptyHashMap(): HashMap { 77 | return new HashMap(); 78 | } 79 | 80 | export function emptyTreeMap(comparator?: Comparator): TreeMap { 81 | return new TreeMap(>Objects.unknownNull(), comparator); 82 | } 83 | 84 | export function newArrayList(iterable?: Iterable | undefined | null): ArrayList { 85 | return new ArrayList(iterable); 86 | } 87 | 88 | export function newLinkedList(iterable?: Iterable | undefined | null): LinkedList { 89 | return new LinkedList(iterable); 90 | } 91 | 92 | export function newHashSet(iterable?: Iterable | undefined | null): HashSet { 93 | return new HashSet(iterable); 94 | } 95 | 96 | export function newLinkedHashSet(iterable?: Iterable | undefined | null): LinkedHashSet { 97 | return new LinkedHashSet(iterable); 98 | } 99 | 100 | export function newTreeSet(iterable?: Iterable | undefined | null, comparator?: Comparator): TreeSet { 101 | return new TreeSet(iterable, comparator); 102 | } 103 | 104 | export function newHashMap(map?: Map | LikeJavaMap | undefined | null): HashMap { 105 | return new HashMap(map); 106 | } 107 | 108 | export function newLinkedHashMap(map?: Map | LikeJavaMap | undefined | null): LinkedHashMap { 109 | return new LinkedHashMap(map); 110 | } 111 | 112 | export function newTreeMap(map?: Map | LikeJavaMap | undefined | null, keyComparator?: Comparator): TreeMap { 113 | return new TreeMap(map, keyComparator); 114 | } 115 | 116 | export function asIterable(obj: any): Iterable { 117 | return Iterables.asIterable(obj); 118 | } 119 | 120 | export function cleanNulls(iterable: LinearCollection): Collection | Array { 121 | if (Types.isArray(iterable)) { 122 | return [...filter(iterable, { 123 | test: function (element: any) { 124 | return !Objects.isNull(element); 125 | } 126 | })]; 127 | } else { 128 | let list = [...iterable]; 129 | let collection = >iterable; 130 | collection.clear(); 131 | collection.addAll(>filter(list, (element) => { 132 | return !Objects.isNull(element); 133 | })); 134 | return collection; 135 | } 136 | } 137 | 138 | export function asSet(iterable: Iterable, comparator?: Comparator): LikeJavaSet { 139 | if (comparator == null) { 140 | return newLinkedHashSet(iterable); 141 | } 142 | return newTreeSet(iterable, comparator); 143 | } 144 | 145 | export function asList(iterable: Iterable): List { 146 | return new ArrayList(iterable); 147 | } 148 | 149 | export function toArray(list?: Collection | Array | Set | Iterable | IterableIterator, newArray?: Array): Array { 150 | let useNewArray: boolean = newArray != null && Types.isArray(newArray); 151 | if (list == null) { 152 | return useNewArray ? >newArray : []; 153 | } 154 | if (useNewArray || !Types.isArray(list)) { 155 | if (newArray == null) { 156 | newArray = []; 157 | } 158 | for (let element of list) { 159 | newArray.push(element); 160 | } 161 | return newArray; 162 | } 163 | return >list; 164 | } 165 | 166 | function _consumeMapEntry(entry: MapEntry, consumerType: ConsumerType, consumer: Consumer | Consumer2 | Function): void { 167 | switch (consumerType) { 168 | case ConsumerType.CONSUMER: 169 | (>>consumer).accept(entry); 170 | break; 171 | case ConsumerType.CONSUMER2: { 172 | (>consumer).accept(entry.key, entry.value); 173 | break; 174 | } 175 | case ConsumerType.FUNCTION: 176 | (consumer).call({}, entry); 177 | break; 178 | } 179 | } 180 | 181 | function _judgePredicateConsumeMapEntry(entry: MapEntry, consumePredicateType: PredicateType, consumePredicate?: Predicate | Predicate2 | Function): boolean { 182 | let consumeable: boolean = true; 183 | switch (consumePredicateType) { 184 | case PredicateType.PREDICATE: 185 | consumeable = (>consumePredicate).test(entry); 186 | break; 187 | case PredicateType.PREDICATE2: 188 | consumeable = (>consumePredicate).test(entry.key, entry.value); 189 | break; 190 | case PredicateType.FUNCTION: 191 | consumeable = (consumePredicate).call({}, entry); 192 | } 193 | return consumeable; 194 | } 195 | 196 | function _judgeBreakConsumeMapEntry(entry: MapEntry, breakPredicateType: PredicateType, breakPredicate?: Predicate | Predicate2 | Function): boolean { 197 | let breakable: boolean = false; 198 | switch (breakPredicateType) { 199 | case PredicateType.PREDICATE: 200 | breakable = (>breakPredicate).test(entry); 201 | break; 202 | case PredicateType.PREDICATE2: 203 | breakable = (>breakPredicate).test(entry.key, entry.value); 204 | break; 205 | case PredicateType.FUNCTION: 206 | breakable = (breakPredicate).call({}, entry); 207 | } 208 | return breakable; 209 | } 210 | 211 | 212 | function _consumeListItem(index: number, element: any, consumerType: ConsumerType, consumer: Consumer | Consumer2 | Function): void { 213 | switch (consumerType) { 214 | case ConsumerType.CONSUMER: 215 | (>consumer).accept(element); 216 | break; 217 | case ConsumerType.CONSUMER2: 218 | (>consumer).accept(index, element); 219 | break; 220 | case ConsumerType.FUNCTION: 221 | (consumer).call({}, element, index); 222 | break; 223 | } 224 | } 225 | 226 | function _judgePredicateConsumeListItem(index: number, element: any, consumePredicateType: PredicateType, consumePredicate?: Predicate | Predicate2 | Function): boolean { 227 | let consumeable: boolean = true; 228 | switch (consumePredicateType) { 229 | case PredicateType.PREDICATE: 230 | consumeable = (>consumePredicate).test(element); 231 | break; 232 | case PredicateType.PREDICATE2: 233 | consumeable = (>consumePredicate).test(index, element); 234 | break; 235 | case PredicateType.FUNCTION: 236 | consumeable = (consumePredicate).call({}, element, index); 237 | } 238 | return consumeable; 239 | } 240 | 241 | function _judgeBreakConsumeListItem(index: number, element: any, breakPredicateType: PredicateType, breakPredicate?: Predicate | Predicate2 | Function): boolean { 242 | let breakable: boolean = false; 243 | switch (breakPredicateType) { 244 | case PredicateType.PREDICATE: 245 | breakable = (>breakPredicate).test(element); 246 | break; 247 | case PredicateType.PREDICATE2: 248 | breakable = (>breakPredicate).test(index, element); 249 | break; 250 | case PredicateType.FUNCTION: 251 | breakable = (breakPredicate).call({}, element, index); 252 | } 253 | return breakable; 254 | } 255 | 256 | 257 | export function forEach(iterable: Iterable | null | undefined, consumer: Consumer | Consumer2 | Function, consumePredicate?: Predicate | Predicate2 | Function | undefined | null, breakPredicate?: Predicate | Predicate2 | Function | undefined | null): void { 258 | if (iterable == null) { 259 | return; 260 | } 261 | iterable = Iterables.asIterable(iterable); 262 | consumePredicate = consumePredicate == null ? truePredicate() : consumePredicate; 263 | let consumePredicateType = Functions.judgePredicateType(consumePredicate); 264 | let consumerType: ConsumerType = Functions.judgeConsumerType(consumer); 265 | breakPredicate = breakPredicate == null ? falsePredicate() : breakPredicate; 266 | let breakPredicateType = Functions.judgePredicateType(breakPredicate); 267 | Preconditions.checkTrue(consumerType != ConsumerType.UNKNOWN, "illegal consumer"); 268 | 269 | let isMap = Types.isMap(iterable); 270 | if (isMap) { 271 | let map; 272 | if (Types.isJavaMap(iterable)) { 273 | map = >iterable; 274 | } else if (Types.isJsMap(iterable)) { 275 | map = new HashMap(>iterable); 276 | } 277 | for (let entry of map) { 278 | if (_judgePredicateConsumeMapEntry(entry, consumePredicateType, consumePredicate)) { 279 | _consumeMapEntry(entry, consumerType, consumer); 280 | } 281 | if (_judgeBreakConsumeMapEntry(entry, breakPredicateType, breakPredicate)) { 282 | break; 283 | } 284 | } 285 | } else { 286 | let index = 0; 287 | for (let element of iterable) { 288 | if (_judgePredicateConsumeListItem(index, element, consumePredicateType, consumePredicate)) { 289 | _consumeListItem(index, element, consumerType, consumer); 290 | } 291 | if (_judgeBreakConsumeListItem(index, element, breakPredicateType, breakPredicate)) { 292 | break; 293 | } 294 | index++; 295 | } 296 | } 297 | 298 | } 299 | 300 | 301 | export function map(iterable: Iterable | null | undefined, mapper: Func | Func2 | Function): List | LikeJavaMap { 302 | let mapperType = Functions.judgeFuncType(mapper); 303 | Preconditions.checkTrue(mapperType != FunctionType.UNKNOWN, "illegal mapper"); 304 | 305 | let isMap = Types.isMap(iterable); 306 | if (isMap) { 307 | const newMap: LikeJavaMap = new HashMap(); 308 | const mapConsumer: Consumer = { 309 | accept(entry: MapEntry) { 310 | switch (mapperType) { 311 | case FunctionType.FUNC: 312 | let newEntry: MapEntry = (, MapEntry>>mapper).apply(entry); 313 | newMap.put(newEntry.key, newEntry.value); 314 | break; 315 | case FunctionType.FUNC2: { 316 | let newEntry2: MapEntry = (>>mapper).apply(entry.key, entry.value); 317 | newMap.put(newEntry2.key, newEntry2.value); 318 | break; 319 | } 320 | case FunctionType.FUNCTION: 321 | let newEntry3: MapEntry = (mapper).call({}, entry); 322 | newMap.put(newEntry3.key, newEntry3.value); 323 | break; 324 | } 325 | } 326 | }; 327 | forEach(iterable, mapConsumer); 328 | return newMap; 329 | } else { 330 | let list = emptyArrayList(); 331 | const listConsumer: Consumer2 = { 332 | accept(index: number, element: any) { 333 | switch (mapperType) { 334 | case FunctionType.FUNC: 335 | list.add((>mapper).apply(element)); 336 | break; 337 | case FunctionType.FUNC2: 338 | list.add((>mapper).apply(index, element)); 339 | break; 340 | case FunctionType.FUNCTION: 341 | list.add((mapper).call({}, element, index)); 342 | break; 343 | } 344 | } 345 | }; 346 | forEach(iterable, listConsumer); 347 | return list; 348 | } 349 | } 350 | 351 | export function filter(iterable: Iterable | undefined | null, predicate: Predicate | Predicate2 | Function, breakPredicate?: Predicate | Predicate2 | Function): Iterable { 352 | let predicateType = Functions.judgePredicateType(predicate); 353 | Preconditions.checkTrue(predicateType != PredicateType.UNKNOWN, "illegal predicate"); 354 | let isMap = Types.isMap(iterable); 355 | if (isMap) { 356 | let newMap: LikeJavaMap = new HashMap(); 357 | forEach(iterable, (entry: MapEntry) => { 358 | newMap.put(entry.key, entry.value); 359 | }, >Objects.unknownNull(), breakPredicate); 360 | return newMap; 361 | } else { 362 | const newList = emptyArrayList(); 363 | forEach(iterable, (element) => { 364 | newList.add(element); 365 | }, predicate, breakPredicate); 366 | return newList; 367 | } 368 | } 369 | 370 | 371 | export function findN(iterable: Iterable | undefined | null, predicate: undefined | null | Predicate | Predicate2 | Function, count: number): any { 372 | Preconditions.checkTrue(Numbers.isInteger(count) && count > 0); 373 | if (iterable == null) { 374 | return null; 375 | } 376 | if (predicate == null) { 377 | predicate = Functions.truePredicate(); 378 | } 379 | let predicateType = Functions.judgePredicateType(predicate); 380 | Preconditions.checkTrue(predicateType != PredicateType.UNKNOWN, "illegal predicate"); 381 | let isMap = Types.isMap(iterable); 382 | if (isMap) { 383 | let newMap: LikeJavaMap = new HashMap(); 384 | forEach(iterable, { 385 | accept(entry: MapEntry) { 386 | newMap.put(entry.key, entry.value); 387 | } 388 | }, predicate, { 389 | test(entry: MapEntry) { 390 | return newMap.size() >= count; 391 | } 392 | }); 393 | return newMap; 394 | } else { 395 | const newList = emptyArrayList(); 396 | forEach(iterable, { 397 | accept(index: number, element: any) { 398 | newList.add(element); 399 | } 400 | }, predicate, { 401 | test(index: number, element: any) { 402 | return newList.size() >= count; 403 | } 404 | }); 405 | return newList; 406 | } 407 | } 408 | 409 | export function findFirst(iterable: Iterable | undefined | null, predicate: Predicate | Predicate2 | Function | null | undefined): any { 410 | let list = asList(findN(iterable, predicate, 1)); 411 | if (list.isEmpty()) { 412 | return null; 413 | } 414 | return list.get(0); 415 | } 416 | 417 | export function flatMap(list: Array | Collection | Set, mapper?: Func | Func2 | Function): List { 418 | let array: Array = []; 419 | if (list != null) { 420 | for (let collection of list) { 421 | if (collection != null) { 422 | array = array.concat([...collection]); 423 | } 424 | } 425 | } 426 | const list0: List = newArrayList(array); 427 | if (mapper != null) { 428 | return >map(list0, mapper); 429 | } 430 | return list0; 431 | } 432 | 433 | export function anyMatch(iterable: Iterable | undefined | null, predicate: Predicate | Predicate2 | Function): boolean { 434 | if (iterable == null) { 435 | return false; 436 | } 437 | let predicateType = Functions.judgePredicateType(predicate); 438 | Preconditions.checkTrue(predicateType != PredicateType.UNKNOWN, "illegal predicate"); 439 | let matched: boolean = false; 440 | forEach(iterable, () => { 441 | matched = true; 442 | }, predicate, () => { 443 | return matched; 444 | }); 445 | return matched; 446 | 447 | } 448 | 449 | export function allMatch(iterable: Iterable | undefined | null, predicate: Predicate | Predicate2 | Function): boolean { 450 | if (iterable == null) { 451 | return false; 452 | } 453 | let matched: boolean = true; 454 | let nonPredicate = Functions.nonPredicateAny(predicate); 455 | forEach(iterable, () => { 456 | matched = false; 457 | }, nonPredicate, () => { 458 | return !matched; 459 | }); 460 | return matched; 461 | } 462 | 463 | 464 | export function noneMatch(iterable: Iterable | undefined | null, predicate: Predicate | Predicate2 | Function): boolean { 465 | if (iterable == null) { 466 | return true; 467 | } 468 | let predicateType = Functions.judgePredicateType(predicate); 469 | Preconditions.checkTrue(predicateType != PredicateType.UNKNOWN, "illegal predicate"); 470 | let unmatched: boolean = true; 471 | forEach(iterable, () => { 472 | unmatched = false; 473 | }, predicate, () => { 474 | return !unmatched; 475 | }); 476 | return unmatched; 477 | } 478 | 479 | 480 | export function removeIf(iterable: Iterable, predicate: Predicate | Predicate2 | Function, returnNewIterable?:boolean):Iterable { 481 | if (predicate == null) { 482 | return iterable; 483 | } 484 | returnNewIterable = returnNewIterable==null? false:returnNewIterable; 485 | // step 1: find all will not removed 486 | let newCollection = filter(iterable, Functions.nonPredicateAny(predicate)); 487 | if(returnNewIterable){ 488 | return newCollection; 489 | } 490 | // step 2: clear all and fill all will not removed 491 | if (Types.isArray(iterable)) { 492 | let array: Array = >iterable; 493 | // clear all 494 | array.splice(0); 495 | array.push(...iterable); 496 | } else if (Types.isJsSet(iterable)) { 497 | let set: Set = >iterable; 498 | set.clear(); 499 | forEach(newCollection, { 500 | accept(element: any) { 501 | set.add(element); 502 | } 503 | }); 504 | } else if (Types.isJsMap(iterable)) { 505 | let map: Map = >iterable; 506 | map.clear(); 507 | for (let entry of newCollection) { 508 | map.set(entry.key, entry.value); 509 | } 510 | } else if (Types.isJavaCollection(iterable)) { 511 | let collection: Collection = >iterable; 512 | collection.clear(); 513 | collection.addAll(>newCollection); 514 | } else if (Types.isJavaMap(iterable)) { 515 | let map: LikeJavaMap = >iterable; 516 | map.clear(); 517 | map.putAll(>newCollection); 518 | } 519 | return iterable; 520 | } 521 | 522 | 523 | export function limit(iterable: Iterable | null | undefined, limit: number): List { 524 | if (iterable == null) { 525 | return emptyArrayList(); 526 | } 527 | Preconditions.checkTrue(limit >= 0); 528 | let list = iterable instanceof AbstractList ? >iterable : newArrayList(iterable); 529 | if (list.size() <= limit) { 530 | return list; 531 | } 532 | return list.subList(0, limit); 533 | } 534 | 535 | export function skip(iterable: Iterable | null | undefined, skip: number) { 536 | if (iterable == null) { 537 | return emptyArrayList(); 538 | } 539 | Preconditions.checkTrue(skip >= 0); 540 | let list = iterable instanceof AbstractList ? >iterable : newArrayList(iterable); 541 | if (list.size() <= skip) { 542 | return emptyArrayList(); 543 | } 544 | return list.subList(skip, list.size()); 545 | } 546 | 547 | export function distinct(iterable: Iterable, comparator?: Comparator): LikeJavaSet { 548 | return newTreeSet(iterable, comparator); 549 | } 550 | 551 | export function reverse(iterable: Iterable, newOne?: boolean): Iterable { 552 | if (iterable == null) { 553 | return []; 554 | } 555 | if (newOne == null) { 556 | newOne = true; 557 | } 558 | if (Types.isArray(iterable)) { 559 | return newOne ? [...iterable].reverse() : (>iterable).reverse(); 560 | } 561 | if (iterable instanceof AbstractList) { 562 | let list: AbstractList = >iterable; 563 | let array: Array = [...list].reverse(); 564 | if (newOne) { 565 | return new ArrayList(array); 566 | } 567 | list.clear(); 568 | for (let element of array) { 569 | list.add(element); 570 | } 571 | return list; 572 | } 573 | if (iterable instanceof Set) { 574 | let set: Set = >iterable; 575 | let array = [...iterable].reverse(); 576 | if (newOne) { 577 | return new Set(array); 578 | } 579 | 580 | set.clear(); 581 | for (let element of array) { 582 | set.add(element); 583 | } 584 | return set; 585 | } 586 | if (iterable instanceof AbstractSet) { 587 | let set: AbstractSet = >iterable; 588 | let array: Array = [...set].reverse(); 589 | if (newOne) { 590 | if (iterable instanceof TreeSet) { 591 | return new TreeSet(array, new ReverseComparator((>iterable).getComparator())); 592 | } 593 | return new LinkedHashSet(array); 594 | } 595 | set.clear(); 596 | if (set instanceof TreeSet) { 597 | let treeSet = >set; 598 | treeSet.setComparator(new ReverseComparator(treeSet.getComparator())); 599 | } 600 | for (let element of array) { 601 | set.add(element); 602 | } 603 | return set; 604 | } 605 | if (iterable instanceof Map) { 606 | let map: Map = >iterable; 607 | let entryArray: Array<[any, any]> = Array.from(map.entries()).reverse(); 608 | if (newOne) { 609 | return new Map(entryArray); 610 | } 611 | map.clear(); 612 | for (let [key, value] of entryArray) { 613 | map.set(key, value); 614 | } 615 | return map; 616 | } 617 | if (iterable instanceof AbstractMap) { 618 | let map: AbstractMap = >iterable; 619 | let entryArray: Array> = [...map].reverse(); 620 | if (newOne) { 621 | let newMap: AbstractMap; 622 | if (iterable instanceof TreeMap) { 623 | newMap = new TreeMap(null, new ReverseComparator((>iterable).getComparator())); 624 | } else { 625 | newMap = new LinkedHashMap(); 626 | } 627 | for (let entry of entryArray) { 628 | newMap.put(entry.key, entry.value); 629 | } 630 | return newMap; 631 | } 632 | map.clear(); 633 | if (iterable instanceof TreeMap) { 634 | let treeMap: TreeMap = >iterable; 635 | treeMap.setComparator(new ReverseComparator(treeMap.getComparator())); 636 | } 637 | for (let entry of entryArray) { 638 | map.put(entry.key, entry.value); 639 | } 640 | return map; 641 | } 642 | return iterable; 643 | } 644 | 645 | export function count(iterable: Iterable, predicate?: Function | Predicate | Predicate2): number { 646 | if (predicate == null) { 647 | return Emptys.getLength(iterable); 648 | } 649 | if (iterable == null) { 650 | return 0; 651 | } 652 | let count = 0; 653 | forEach(iterable, function () { 654 | count++; 655 | }, predicate); 656 | return count; 657 | } 658 | 659 | export function addAll(iterable: Iterable, appendment: Iterable): void { 660 | Preconditions.checkNonNull(iterable); 661 | Preconditions.checkNonNull(appendment); 662 | if (iterable instanceof Array) { 663 | let array: Array = >iterable; 664 | array.splice(array.length, 0, ...appendment); 665 | return; 666 | } 667 | if (iterable instanceof Set) { 668 | let set: Set = >iterable; 669 | for (let element of appendment) { 670 | set.add(element); 671 | } 672 | return; 673 | } 674 | if (iterable instanceof AbstractCollection) { 675 | (>iterable).addAll(appendment); 676 | return; 677 | } 678 | if (iterable instanceof AbstractMap) { 679 | let map: AbstractMap = >iterable; 680 | for (let entry of appendment) { 681 | if (entry instanceof Array) { 682 | Preconditions.checkTrue((>entry).length >= 2); 683 | map.put(entry[0], entry[1]) 684 | } else if (entry instanceof SimpleMapEntry) { 685 | map.put(entry.key, entry.value); 686 | } 687 | } 688 | return; 689 | } 690 | if (iterable instanceof Map) { 691 | let map: Map = >iterable; 692 | for (let entry of appendment) { 693 | if (entry instanceof Array) { 694 | Preconditions.checkTrue((>entry).length >= 2); 695 | map.set(entry[0], entry[1]) 696 | } else if (entry instanceof SimpleMapEntry) { 697 | map.set(entry.key, entry.value); 698 | } 699 | } 700 | return; 701 | } 702 | } 703 | 704 | export function contains(iterable: Iterable | undefined | null, element: any, deep?: boolean): boolean { 705 | if (Emptys.isEmpty(iterable)) { 706 | return false; 707 | } 708 | return anyMatch(iterable, (e) => { 709 | return Objects.equals(e, element, deep); 710 | }); 711 | } 712 | 713 | /** 714 | * Judge every element in {judgement} will in the {iterable} 715 | * @param iterable 716 | * @param judgement 717 | */ 718 | export function containsAll(iterable: Iterable | null | undefined, judgement: Iterable, deep?: boolean): boolean { 719 | if (Emptys.isEmpty(iterable)) { 720 | return false; 721 | } 722 | Preconditions.checkNonNull(judgement); 723 | return allMatch(judgement, (element) => { 724 | return contains(iterable, element, deep); 725 | }); 726 | } 727 | 728 | export function containsAny(iterable: Iterable | null | undefined, judgement: Iterable, deep?: boolean): boolean { 729 | if (Emptys.isEmpty(iterable)) { 730 | return false; 731 | } 732 | Preconditions.checkNonNull(judgement); 733 | return anyMatch(judgement, (element) => { 734 | return contains(iterable, element, deep); 735 | }); 736 | } 737 | 738 | export function containsNone(iterable: Iterable | null | undefined, judgement: Iterable, deep?: boolean): boolean { 739 | if (Emptys.isEmpty(iterable)) { 740 | return true; 741 | } 742 | return noneMatch(judgement, (element) => { 743 | return contains(iterable, element, deep); 744 | }); 745 | } 746 | 747 | export function intersection(iterable1: Iterable | undefined | null, iterable2: Iterable | undefined | null): Iterable { 748 | if (iterable2 == null || iterable1 == null) { 749 | return []; 750 | } 751 | let isMapOfIterable1 = Types.isMap(iterable1); 752 | let isMapOfIterable2 = Types.isMap(iterable2); 753 | Preconditions.checkTrue(isMapOfIterable1 == isMapOfIterable2); 754 | if (isMapOfIterable1) { 755 | let result: LinkedHashMap = emptyLinkedHashMap(); 756 | let map1: LinkedHashMap = (iterable1 instanceof Map) ? newLinkedHashMap(>iterable1) : newLinkedHashMap(>iterable1); 757 | let map2: LinkedHashMap = (iterable2 instanceof Map) ? newLinkedHashMap(>iterable2) : newLinkedHashMap(>iterable2); 758 | let union: LinkedHashMap = newLinkedHashMap(map1); 759 | union.putAll(map2); 760 | forEach(union, (key, value) => { 761 | result.put(key, value); 762 | }, (entry) => { 763 | return contains(map1, entry, true) && contains(map2, entry, true); 764 | }); 765 | return result; 766 | } else { 767 | let result: LinkedHashSet = emptyLinkedHashSet(); 768 | let set1: LinkedHashSet = newLinkedHashSet(iterable1); 769 | let set2: LinkedHashSet = newLinkedHashSet(iterable2); 770 | let union: LinkedHashSet = newLinkedHashSet(set1); 771 | union.addAll(set2); 772 | forEach(union, (element) => { 773 | result.add(element) 774 | }, (element) => { 775 | return set1.contains(element) && set2.contains(element); 776 | }); 777 | return result; 778 | } 779 | } 780 | 781 | export function union(iterable1: Iterable | undefined | null, iterable2: Iterable | undefined | null) { 782 | let isMapOfIterable1 = Types.isMap(iterable1); 783 | let isMapOfIterable2 = Types.isMap(iterable2); 784 | Preconditions.checkTrue(isMapOfIterable1 == isMapOfIterable2); 785 | if (isMapOfIterable1) { 786 | let map1: LinkedHashMap = (iterable1 instanceof Map) ? newLinkedHashMap(>iterable1) : newLinkedHashMap(>iterable1); 787 | let map2: LinkedHashMap = (iterable2 instanceof Map) ? newLinkedHashMap(>iterable2) : newLinkedHashMap(>iterable2); 788 | let union: LinkedHashMap = newLinkedHashMap(map1); 789 | union.putAll(map2); 790 | return union; 791 | } else { 792 | let set1: LinkedHashSet = newLinkedHashSet(iterable1); 793 | let set2: LinkedHashSet = newLinkedHashSet(iterable2); 794 | let union: LinkedHashSet = newLinkedHashSet(set1); 795 | union.addAll(set2); 796 | return union; 797 | } 798 | } 799 | 800 | export function groupBy(classifier: Func | Func2 | Function, mapFactory: Supplier0>>): LikeJavaMap> { 801 | return >>this.collect(Collectors.groupingBy(classifier, mapFactory)); 802 | } 803 | 804 | export function partitionBy(iterable: Iterable | undefined | null, classifier: Func | Func2 | Function): List> { 805 | let map: LikeJavaMap> = >>Collectors.collect(iterable, partioningBy(classifier)); 806 | return asList(map.values()) 807 | } 808 | 809 | export function partitionBySize(iterable: Iterable | undefined | null, size: number): List> { 810 | Preconditions.checkTrue(size > 0); 811 | return partitionBy(iterable, { 812 | apply(index: number, element: any) { 813 | // return Numbers.parseInt(index / element)+ (index % size ==0 ? 1 :0) 814 | return index % size; 815 | } 816 | }); 817 | } 818 | 819 | /** 820 | * append to collection 821 | */ 822 | export function concat(collection: Set | Array | Collection, appentments: Set | Array | Collection): Array { 823 | let newList: Array = []; 824 | if (collection != null) { 825 | addAll(newList, collection); 826 | } 827 | if (appentments != null) { 828 | addAll(newList, appentments); 829 | } 830 | return newList; 831 | } -------------------------------------------------------------------------------- /src/main/Comparators.ts: -------------------------------------------------------------------------------- 1 | import * as Objects from "./Objects"; 2 | import * as Preconditions from "./Preconditions"; 3 | import * as Types from "./Types"; 4 | import * as Functions from "./Functions"; 5 | import {Func2, FunctionType, truePredicate} from "./Functions"; 6 | import {List} from "./Iterables"; 7 | import * as Collects from "./Collects"; 8 | 9 | export interface Comparator { 10 | compare(e1: E, e2: E): number; 11 | } 12 | 13 | export abstract class AbstractComparator implements Comparator { 14 | /** 15 | * @param e1 the new element 16 | * @param e2 the element in a collection 17 | * @return if e1 > e2 , return a positive number; 18 | * if e1 < e2 , return a negative number; 19 | * if e1 equals e2, return 0; 20 | */ 21 | abstract compare(e1: E, e2: E): number; 22 | } 23 | 24 | export function isComparator(c: any) { 25 | if (Objects.isNull(c)) { 26 | return false; 27 | } 28 | if (c instanceof AbstractComparator) { 29 | return true; 30 | } 31 | if (Types.isFunction(c["compare"])) { 32 | let func: Function = c["compare"]; 33 | return func.length >= 2; 34 | } 35 | return false; 36 | } 37 | 38 | export class NumberComparator extends AbstractComparator { 39 | compare(e1: number, e2: number): number { 40 | return e1 - e2; 41 | } 42 | } 43 | 44 | export class StringComparator extends AbstractComparator { 45 | compare(e1: string, e2: string): number { 46 | if (e1 == null || e2 == null) { 47 | if (e1 == null && e2 == null) { 48 | return 0; 49 | } 50 | return e1 == null ? -1 : 1; 51 | } 52 | let minLength: number = Math.min(e1.length, e2.length); 53 | let i: number = 0; 54 | while (i < minLength) { 55 | let delta: number = e1.charCodeAt(i) - e2.charCodeAt(i); 56 | if (delta == 0) { 57 | i++; 58 | } else { 59 | return delta; 60 | } 61 | } 62 | return e1.length - e2.length; 63 | } 64 | } 65 | 66 | export class DateComparator extends AbstractComparator { 67 | compare(e1: Date, e2: Date): number { 68 | return e1.getTime() - e2.getTime(); 69 | } 70 | } 71 | 72 | export class BooleanComparator extends AbstractComparator { 73 | compare(e1: Boolean, e2: Boolean): number { 74 | if (e1 == e2) { 75 | return 0; 76 | } 77 | return e1 ? 1 : -1; 78 | } 79 | } 80 | 81 | export class HashedComparator extends AbstractComparator { 82 | compare(e1: E, e2: E): number { 83 | return Objects.hashCode(e1) - Objects.hashCode(e2); 84 | } 85 | } 86 | 87 | export class ReverseComparator extends AbstractComparator { 88 | private readonly comparator: Comparator; 89 | 90 | constructor(comparator: Comparator) { 91 | super(); 92 | this.comparator = comparator; 93 | } 94 | 95 | compare(e1: E, e2: E): number { 96 | return this.comparator.compare(e2, e1); 97 | } 98 | } 99 | 100 | export class IsComparator extends AbstractComparator { 101 | constructor() { 102 | super(); 103 | } 104 | 105 | compare(e1: E, e2: E): number { 106 | return e1 === e2 ? 0 : 1; 107 | } 108 | } 109 | 110 | export class EqualsComparator extends AbstractComparator { 111 | constructor() { 112 | super(); 113 | } 114 | 115 | compare(e1: E, e2: E): number { 116 | return Objects.equals(e1, e2, true) ? 0 : 1; 117 | } 118 | } 119 | 120 | export class DelegatableComparator extends AbstractComparator { 121 | protected readonly comp: Comparator; 122 | 123 | constructor(comparator: Comparator) { 124 | super(); 125 | this.comp = comparator; 126 | } 127 | 128 | compare(e1: E, e2: E): number { 129 | return this.comp.compare(e1, e2); 130 | } 131 | } 132 | 133 | export class CompositeComparator extends AbstractComparator { 134 | private readonly comps: List> = Collects.newArrayList(); 135 | private started: boolean = false; 136 | 137 | constructor() { 138 | super(); 139 | } 140 | 141 | addComparator(comparator: Func2 | Comparator | Function) { 142 | if (!this.started) { 143 | this.comps.add(new FunctionComparator(comparator)); 144 | } 145 | } 146 | 147 | compare(e1: E, e2: E): number { 148 | this.started = true; 149 | Preconditions.checkTrue(!this.comps.isEmpty()); 150 | let result: number = 0; 151 | Collects.forEach(this.comps, (comparator: Comparator) => { 152 | result = comparator.compare(e1, e2); 153 | }, truePredicate(), () => { 154 | return result != 0; 155 | }); 156 | return result; 157 | } 158 | 159 | } 160 | 161 | 162 | export class FunctionComparator extends AbstractComparator { 163 | private readonly comp: Function | Func2 | Comparator; 164 | 165 | constructor(f: Function | Func2 | Comparator) { 166 | super(); 167 | Preconditions.checkTrue(Functions.judgeFuncType(f) != FunctionType.UNKNOWN, "argument is not a function"); 168 | this.comp = f; 169 | } 170 | 171 | compare(e1: E, e2: E): number { 172 | let ret = isComparator(this.comp) ? (>this.comp).compare(e1, e2) : Functions.callFunction(this.comp, e1, e2); 173 | if (ret) { 174 | return 0; 175 | } 176 | if (Types.isNumber(ret)) { 177 | return ret; 178 | } 179 | return 1; 180 | } 181 | } 182 | 183 | export function functionComparator(f: Function | Func2 | Comparator): FunctionComparator { 184 | return new FunctionComparator(f); 185 | } 186 | 187 | export function wrapComparators(...funcs: Array | Comparator>): CompositeComparator { 188 | let comparator: CompositeComparator = new CompositeComparator(); 189 | Collects.forEach(funcs, (c: Function | Func2 | Comparator) => { 190 | comparator.addComparator(c); 191 | }, (c: Function | Func2 | Comparator) => { 192 | return c != null; 193 | }); 194 | return comparator; 195 | } 196 | 197 | export class ToStringComparator extends DelegatableComparator { 198 | 199 | constructor() { 200 | super(new StringComparator()); 201 | } 202 | 203 | compare(e1: any, e2: any): number { 204 | return this.comp.compare(e1 == null ? e1 : e1.toString(), e2 == null ? e2 : e2.toString()); 205 | } 206 | 207 | } 208 | 209 | export class ObjectComparator extends AbstractComparator { 210 | compare(e1: any, e2: any): number { 211 | if (e1 == e2) { 212 | return 0; 213 | } 214 | if (e1 == null) { 215 | return -1; 216 | } 217 | if (e2 == null) { 218 | return 1; 219 | } 220 | let type1 = Types.getType(e1); 221 | let type2 = Types.getType(e2); 222 | if (type1 === type2) { 223 | if (type1 == String) { 224 | return new StringComparator().compare(e1, e2); 225 | } 226 | if (type1 == Number) { 227 | return new NumberComparator().compare(e1, e2); 228 | } 229 | if (type2 == Boolean) { 230 | return new BooleanComparator().compare(e1, e2); 231 | } 232 | if (type1 == Date) { 233 | return new DateComparator().compare(e1, e2); 234 | } 235 | } 236 | return new HashedComparator().compare(e1, e2); 237 | } 238 | } -------------------------------------------------------------------------------- /src/main/Dates.ts: -------------------------------------------------------------------------------- 1 | import * as Types from "./Types"; 2 | export function hashCode(date: Date): number { 3 | return date.getTime(); 4 | } 5 | 6 | export function equals(date:Date, date2:number|string|Date|any) { 7 | if (date2 instanceof Date) { 8 | return date.getTime() == date2.getTime(); 9 | } 10 | if (Types.isString(date2)) { 11 | return (date.toLocaleString() == date2 || date.toUTCString() == date2 || ("" + date.getTime()) == date2); 12 | } 13 | if(Types.isNumber(date2)){ 14 | return date.getTime()==date2; 15 | } 16 | return false; 17 | } -------------------------------------------------------------------------------- /src/main/Delegatables.ts: -------------------------------------------------------------------------------- 1 | export interface Delegatable { 2 | getDelegate(): E; 3 | 4 | setDelegate(e: E): void; 5 | } -------------------------------------------------------------------------------- /src/main/Emptys.ts: -------------------------------------------------------------------------------- 1 | import * as Types from "./Types"; 2 | import {AbstractCollection, AbstractMap, LikeJavaSet} from "./Iterables"; 3 | 4 | export function isNull(obj: any): boolean { 5 | return obj == undefined || obj == null; 6 | } 7 | 8 | export function isNotNull(obj: any): boolean { 9 | return !isNull(obj); 10 | } 11 | 12 | export function getLength(obj: any): number { 13 | if (isNull(obj)) { 14 | return 0; 15 | } 16 | 17 | if (Types.isString(obj)) { 18 | return (obj).length; 19 | } 20 | 21 | if (Types.isNumber(obj)) { 22 | return 1; 23 | } 24 | 25 | // Array 26 | if (Types.isArray(obj)) { 27 | return (>obj).length; 28 | } 29 | 30 | // JavaList, JavaSet 31 | if (Types.isJavaCollection(obj)) { 32 | return (>obj).size(); 33 | } 34 | 35 | // Set 36 | if (Types.isSet(obj)) { 37 | if (Types.isJsSet(obj)) { 38 | return (>obj).size; 39 | } 40 | if (Types.isJavaSet(obj)) { 41 | return (>obj).size(); 42 | } 43 | } 44 | if (Types.isWeakSet(obj)) { 45 | return 0; 46 | } 47 | 48 | if (Types.isMap(obj)) { 49 | if (Types.isJsMap(obj)) { 50 | return (>obj).size; 51 | } 52 | if (Types.isJavaMap(obj)) { 53 | return (>obj).size(); 54 | } 55 | } 56 | return 1; 57 | } 58 | 59 | export function isEmpty(obj: any): boolean { 60 | if (isNull(obj)) { 61 | return true; 62 | } 63 | if (Types.isNumber(obj)) { 64 | return obj == 0; 65 | } 66 | 67 | if (Types.isString(obj)) { 68 | return (obj).length == 0; 69 | } 70 | 71 | if (Types.isArray(obj)) { 72 | return (>obj).length == 0 73 | } 74 | 75 | if (Types.isJavaCollection(obj)) { 76 | return (>obj).isEmpty(); 77 | } 78 | 79 | if (Types.isJsSet(obj)) { 80 | return (>obj).size == 0; 81 | } 82 | 83 | if (Types.isJavaMap(obj)) { 84 | return (>obj).size() == 0; 85 | } 86 | 87 | if (Types.isJsMap(obj)) { 88 | return (>obj).size == 0; 89 | } 90 | 91 | if (Types.isSimpleObject(obj)) { 92 | return isEmpty(Object.keys(obj)); 93 | } 94 | 95 | return false; 96 | } 97 | 98 | export function isNotEmpty(obj: any): boolean { 99 | return !isEmpty(obj); 100 | } -------------------------------------------------------------------------------- /src/main/Exceptions.ts: -------------------------------------------------------------------------------- 1 | import * as Types from './Types'; 2 | 3 | export class RuntimeException extends Error { 4 | constructor(message: string | String | Function) { 5 | super(); 6 | this.message = Types.isFunction(message) ? (message)() : message; 7 | } 8 | } 9 | 10 | export class IllegalArgumentException extends RuntimeException{ 11 | constructor(message: string | String | Function) { 12 | if(message==null){ 13 | message="Illegal argument"; 14 | } 15 | super(message); 16 | } 17 | } 18 | 19 | export class IndexOutboundException extends RuntimeException { 20 | constructor(message?: string | String | Function | undefined | null) { 21 | if (message == null) { 22 | message = "Index outbound"; 23 | } 24 | super(message); 25 | } 26 | } 27 | 28 | export class UnsupportOperationException extends RuntimeException { 29 | constructor(message?: string) { 30 | super(message ? message : "Unsupport operation"); 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/Formatters.ts: -------------------------------------------------------------------------------- 1 | export interface Formatter { 2 | format(data: DATA, params?: Array): O; 3 | } 4 | -------------------------------------------------------------------------------- /src/main/Functions.ts: -------------------------------------------------------------------------------- 1 | import * as Types from "./Types"; 2 | import * as Preconditions from "./Preconditions"; 3 | import * as Collects from "./Collects"; 4 | import * as Objects from "./Objects"; 5 | import * as Emptys from "./Emptys"; 6 | import {ArrayList, MapEntry} from "./Iterables"; 7 | import {IllegalArgumentException} from "./Exceptions"; 8 | import * as Comparators from "./Comparators"; 9 | import {Comparator, FunctionComparator, IsComparator} from "./Comparators"; 10 | 11 | export interface Func { 12 | apply(input: I): O; 13 | } 14 | 15 | export interface Func2 { 16 | apply(i1: I1, i2: I2): O; 17 | } 18 | 19 | export enum FunctionType { 20 | UNKNOWN, 21 | FUNC, 22 | FUNC2, 23 | FUNCTION 24 | } 25 | 26 | export function noopFunction():Function { 27 | return function () { 28 | 29 | }; 30 | } 31 | 32 | export function noopFunc():Func { 33 | return { 34 | apply(i:any){ 35 | return i; 36 | } 37 | }; 38 | } 39 | 40 | export function noopFunc2():Func2 { 41 | return { 42 | apply(i:any, i2:any){ 43 | return i; 44 | } 45 | }; 46 | } 47 | 48 | export function judgeFuncType(mapper?: any | Func | Func2 | Function): FunctionType { 49 | if (mapper == null) { 50 | return FunctionType.UNKNOWN; 51 | } 52 | let hasApplyMethod = Types.isFunction(mapper["apply"]); 53 | if (hasApplyMethod) { 54 | if (mapper["apply"] == Function.apply) { 55 | hasApplyMethod = false; 56 | } 57 | } 58 | if (!hasApplyMethod) { 59 | let consumerIsFunction = Types.isFunction(mapper); 60 | if (consumerIsFunction) { 61 | return FunctionType.FUNCTION; 62 | } 63 | } else { 64 | if ((mapper["apply"]).length == 1) { 65 | return FunctionType.FUNC; 66 | } else if ((mapper["apply"]).length >= 2) { 67 | return FunctionType.FUNC2; 68 | } 69 | } 70 | return FunctionType.UNKNOWN; 71 | } 72 | 73 | export function callFunction(func: Func | Func2 | Function, ...args: any): any { 74 | let type: FunctionType = judgeFuncType(func); 75 | Preconditions.checkTrue(type != FunctionType.UNKNOWN, "not a function"); 76 | return mapping(func, args); 77 | } 78 | 79 | /** 80 | * @param mapperType the mapper type 81 | * @param index current index 82 | * @param element the element in a collection 83 | */ 84 | export function buildArgumentsForCollection(mapperType: FunctionType|PredicateType|ConsumerType, element: any, index: number): Array { 85 | let args: Array = []; 86 | switch (mapperType) { 87 | case 3: 88 | args.push(element, index); 89 | break; 90 | case 2: 91 | args.push(index, element); 92 | break; 93 | case 1: 94 | args.push(element); 95 | break; 96 | default: 97 | throw new IllegalArgumentException("Illegal FunctionType: UNKNOWN"); 98 | break; 99 | } 100 | return args; 101 | } 102 | 103 | export function buildArgumentsForMap(mapperType: FunctionType|PredicateType|ConsumerType, entry: MapEntry): Array { 104 | let args: Array = []; 105 | switch (mapperType) { 106 | case 3: 107 | args.push(entry); 108 | break; 109 | case 2: 110 | args.push(entry.key, entry.value); 111 | break; 112 | case 1: 113 | args.push(entry); 114 | break; 115 | default: 116 | throw new IllegalArgumentException("Illegal FunctionType: UNKNOWN"); 117 | break; 118 | } 119 | return args; 120 | } 121 | 122 | export function mapping(mapper: Func | Func2 | Function, ...args): any { 123 | let mapperType = judgeFuncType(mapper); 124 | let result; 125 | switch (mapperType) { 126 | case FunctionType.FUNC: 127 | result = (>mapper).apply(args[0]); 128 | break; 129 | case FunctionType.FUNC2: 130 | result = (>mapper).apply(args[0], args[1]); 131 | break; 132 | case FunctionType.FUNCTION: 133 | result = (mapper).apply({}, args); 134 | break; 135 | } 136 | return result; 137 | } 138 | 139 | export function mappingCollectionElement(mapper: Func | Func2 | Function, element: any, index: number): any { 140 | let mapperType = judgeFuncType(mapper); 141 | let args: Array = buildArgumentsForCollection(mapperType, element, index); 142 | return mapping(mapper, args); 143 | } 144 | 145 | export function mappingMapEntry(mapper: Func | Func2 | Function, entry: MapEntry): any { 146 | let mapperType = judgeFuncType(mapper); 147 | let args: Array = buildArgumentsForMap(mapperType, entry); 148 | return mapping(mapper, args); 149 | } 150 | 151 | export interface Consumer { 152 | accept(i: I); 153 | } 154 | 155 | export interface Consumer2 { 156 | accept(i1: I1, i2: I2); 157 | } 158 | 159 | export interface IndexedConsumer2 extends Consumer2 { 160 | index: number; 161 | } 162 | 163 | 164 | export function consume(consumer: Consumer | Consumer2 | Function, ...args): any { 165 | let consumerType = judgeConsumerType(consumer); 166 | let result; 167 | switch (consumerType) { 168 | case ConsumerType.CONSUMER: 169 | result = (>consumer).accept(args[0]); 170 | break; 171 | case ConsumerType.CONSUMER2: 172 | result = (>consumer).accept(args[0], args[1]); 173 | break; 174 | case ConsumerType.FUNCTION: 175 | result = (consumer).apply({}, args); 176 | break; 177 | } 178 | return result; 179 | } 180 | 181 | export function consumeCollectionElement(consumer: Consumer | Consumer2 | Function, element: any, index: number): void { 182 | let consumerType:ConsumerType = judgeConsumerType(consumer); 183 | let args: Array = buildArgumentsForCollection(consumerType, element, index); 184 | consume(consumer, args); 185 | } 186 | 187 | export function consumeMapEntry(consumer: Consumer | Consumer2 | Function, entry: MapEntry): void { 188 | let consumerType:ConsumerType = judgeConsumerType(consumer); 189 | let args: Array = buildArgumentsForMap(consumerType, entry); 190 | consume(consumer, args); 191 | } 192 | 193 | export function callConsumer(consumer: Consumer | Consumer2 | Function, ...args):void { 194 | if (isPredicate(consumer)) { 195 | consume(consumer, args); 196 | } 197 | } 198 | 199 | 200 | export enum ConsumerType { 201 | UNKNOWN, 202 | CONSUMER, 203 | CONSUMER2, 204 | FUNCTION 205 | } 206 | 207 | export function judgeConsumerType(consumer: Consumer | Consumer2 | Function): ConsumerType { 208 | if (consumer == null) { 209 | return ConsumerType.UNKNOWN; 210 | } 211 | let hasAcceptMethod = Types.isFunction(consumer["accept"]); 212 | 213 | if (!hasAcceptMethod) { 214 | let consumerIsFunction = Types.isFunction(consumer); 215 | if (consumerIsFunction) { 216 | return ConsumerType.FUNCTION; 217 | } 218 | } else { 219 | if ((consumer["accept"]).length == 1) { 220 | return ConsumerType.CONSUMER; 221 | } else { 222 | return ConsumerType.CONSUMER2; 223 | } 224 | } 225 | return ConsumerType.UNKNOWN; 226 | } 227 | 228 | export function noopConsumer(): Consumer { 229 | return { 230 | accept(i: any) { 231 | } 232 | }; 233 | } 234 | 235 | export function noopConsumer2(): Consumer2 { 236 | return { 237 | accept(i: any, i2: any) { 238 | } 239 | }; 240 | } 241 | 242 | export interface Supplier0 { 243 | get(): O; 244 | } 245 | 246 | export interface Supplier { 247 | get(i: I): O; 248 | } 249 | 250 | export interface Supplier2 { 251 | get(i1: I1, i2: I2): O; 252 | } 253 | 254 | export interface Predicate { 255 | test(i: I): boolean; 256 | } 257 | 258 | export interface Predicate2 { 259 | test(i1: I1, i2: I2): boolean; 260 | } 261 | 262 | 263 | export enum PredicateType { 264 | UNKNOWN, 265 | PREDICATE, 266 | PREDICATE2, 267 | FUNCTION 268 | } 269 | 270 | 271 | export function test(predicate: Predicate | Predicate2 | Function, ...args): any { 272 | let predicateType = judgePredicateType(predicate); 273 | let result; 274 | switch (predicateType) { 275 | case PredicateType.PREDICATE: 276 | result = (>predicate).apply(args[0]); 277 | break; 278 | case PredicateType.PREDICATE2: 279 | result = (>predicate).apply(args[0], args[1]); 280 | break; 281 | case PredicateType.FUNCTION: 282 | result = (predicate).apply({}, args); 283 | break; 284 | } 285 | return result; 286 | } 287 | 288 | export function testCollectionElement(predicate: Predicate | Predicate2 | Function, element: any, index: number): any { 289 | let predicateType:PredicateType = judgePredicateType(predicate); 290 | let args: Array = buildArgumentsForCollection(predicateType, element, index); 291 | return test(predicate, args); 292 | } 293 | 294 | export function testMapEntry(predicate: Predicate | Predicate2 | Function, entry: MapEntry): any { 295 | let predicateType:PredicateType = judgePredicateType(predicate); 296 | let args: Array = buildArgumentsForMap(predicateType, entry); 297 | return test(predicate, args); 298 | } 299 | 300 | export function callPredicate(predicate: any | Predicate | Predicate2 | Function, ...args): boolean { 301 | if (isPredicate(predicate)) { 302 | test(predicate, args); 303 | } 304 | return false; 305 | } 306 | 307 | export function isPredicate(predicate?: any | Predicate | Predicate2 | Function): boolean { 308 | return judgePredicateType(predicate) != PredicateType.UNKNOWN; 309 | } 310 | 311 | export function judgePredicateType(predicate?: Predicate | Predicate2 | Function | undefined | null): PredicateType { 312 | if (predicate == null) { 313 | return PredicateType.UNKNOWN; 314 | } 315 | let hasTestMethod = Types.isFunction(predicate["test"]); 316 | 317 | if (!hasTestMethod) { 318 | let predicateIsFunction = Types.isFunction(predicate); 319 | if (predicateIsFunction) { 320 | return PredicateType.FUNCTION; 321 | } 322 | } else { 323 | if ((predicate["test"]).length == 1) { 324 | return PredicateType.PREDICATE; 325 | } else { 326 | return PredicateType.PREDICATE2; 327 | } 328 | } 329 | return PredicateType.UNKNOWN; 330 | } 331 | 332 | 333 | export class IsNullPredicate implements Predicate { 334 | test(i: any): boolean { 335 | return Emptys.isNull(i); 336 | } 337 | } 338 | 339 | export function isNullPredicate(): Predicate { 340 | return new IsNullPredicate(); 341 | } 342 | 343 | export class AllPredicate implements Predicate { 344 | private readonly predicates: ArrayList> = new ArrayList>(); 345 | 346 | constructor(predicates: Iterable>) { 347 | Preconditions.checkNonNull(predicates); 348 | for (let predicate of predicates) { 349 | if (predicate != null) { 350 | this.predicates.add(predicate); 351 | } 352 | } 353 | } 354 | 355 | test(i: any): boolean { 356 | let matched: boolean = true; 357 | for (let predicate of this.predicates) { 358 | matched = predicate.test(i); 359 | if (!matched) { 360 | return false; 361 | } 362 | } 363 | return true; 364 | } 365 | } 366 | 367 | export class AllPredicate2 implements Predicate2 { 368 | private readonly predicates: ArrayList> = new ArrayList>(); 369 | 370 | constructor(predicates: Iterable>) { 371 | Preconditions.checkNonNull(predicates); 372 | for (let predicate of predicates) { 373 | if (predicate != null) { 374 | this.predicates.add(predicate); 375 | } 376 | } 377 | } 378 | 379 | test(i: any, i2: any): boolean { 380 | let matched: boolean = true; 381 | for (let predicate of this.predicates) { 382 | matched = predicate.test(i, i2); 383 | if (!matched) { 384 | return false; 385 | } 386 | } 387 | return true; 388 | } 389 | } 390 | 391 | export function allPredicate(predicates: Iterable>) { 392 | return new AllPredicate(predicates); 393 | } 394 | 395 | export function allPredicate2(predicates: Iterable>) { 396 | return new AllPredicate2(predicates); 397 | } 398 | 399 | export class AnyPredicate implements Predicate { 400 | private readonly predicates: ArrayList> = new ArrayList>(); 401 | 402 | constructor(predicates: Iterable>) { 403 | Preconditions.checkNonNull(predicates); 404 | for (let predicate of predicates) { 405 | if (predicate != null) { 406 | this.predicates.add(predicate); 407 | } 408 | } 409 | } 410 | 411 | test(i: any): boolean { 412 | let matched: boolean = false; 413 | for (let predicate of this.predicates) { 414 | matched = predicate.test(i); 415 | if (matched) { 416 | return true; 417 | } 418 | } 419 | return false; 420 | } 421 | } 422 | 423 | export class AnyPredicate2 implements Predicate2 { 424 | private readonly predicates: ArrayList> = new ArrayList>(); 425 | 426 | constructor(predicates: Iterable>) { 427 | Preconditions.checkNonNull(predicates); 428 | for (let predicate of predicates) { 429 | if (predicate != null) { 430 | this.predicates.add(predicate); 431 | } 432 | } 433 | } 434 | 435 | test(i: any, i2: any): boolean { 436 | let matched: boolean = false; 437 | for (let predicate of this.predicates) { 438 | matched = predicate.test(i, i2); 439 | if (matched) { 440 | return true; 441 | } 442 | } 443 | return false; 444 | } 445 | } 446 | 447 | export function anyPredicate(predicates: Iterable>) { 448 | return new AnyPredicate(predicates); 449 | } 450 | 451 | export function anyPredicate2(predicates: Iterable>) { 452 | return new AnyPredicate2(predicates); 453 | } 454 | 455 | export class NonePredicate implements Predicate { 456 | private readonly predicates: ArrayList> = new ArrayList>(); 457 | 458 | constructor(predicates: Iterable>) { 459 | Preconditions.checkNonNull(predicates); 460 | for (let predicate of predicates) { 461 | if (predicate != null) { 462 | this.predicates.add(predicate); 463 | } 464 | } 465 | } 466 | 467 | test(i: any): boolean { 468 | let matched: boolean = true; 469 | for (let predicate of this.predicates) { 470 | matched = predicate.test(i); 471 | if (matched) { 472 | return false; 473 | } 474 | } 475 | return true; 476 | } 477 | } 478 | 479 | export class NonePredicate2 implements Predicate2 { 480 | private readonly predicates: ArrayList> = new ArrayList>(); 481 | 482 | constructor(predicates: Iterable>) { 483 | Preconditions.checkNonNull(predicates); 484 | for (let predicate of predicates) { 485 | if (predicate != null) { 486 | this.predicates.add(predicate); 487 | } 488 | } 489 | } 490 | 491 | test(i: any, i2: any): boolean { 492 | let matched: boolean = true; 493 | for (let predicate of this.predicates) { 494 | matched = predicate.test(i, i2); 495 | if (matched) { 496 | return false; 497 | } 498 | } 499 | return true; 500 | } 501 | } 502 | 503 | export function nonePredicate(predicates: Iterable>) { 504 | return new NonePredicate(predicates); 505 | } 506 | 507 | export function nonePredicate2(predicates: Iterable>) { 508 | return new NonePredicate2(predicates); 509 | } 510 | 511 | export class NonPredicate implements Predicate { 512 | private readonly predicate: Predicate; 513 | 514 | constructor(predicate: Predicate) { 515 | this.predicate = predicate; 516 | } 517 | 518 | test(i: any): boolean { 519 | return !this.predicate.test(i); 520 | } 521 | } 522 | 523 | export class NonPredicate2 implements Predicate2 { 524 | private readonly predicate: Predicate2; 525 | 526 | constructor(predicate: Predicate2) { 527 | this.predicate = predicate; 528 | } 529 | 530 | test(i: any, i2: any): boolean { 531 | return !this.predicate.test(i, i2); 532 | } 533 | } 534 | 535 | export function nonPredicate(predicate: Predicate) { 536 | return new NonPredicate(predicate); 537 | } 538 | 539 | export function nonPredicate2(predicate: Predicate2) { 540 | return new NonPredicate2(predicate); 541 | } 542 | 543 | export function nonPredicateAny(predicate: Predicate | Predicate2 | Function) { 544 | let predicateType = judgePredicateType(predicate); 545 | Preconditions.checkTrue(predicateType != PredicateType.UNKNOWN, "illegal predicate"); 546 | let p: Predicate | Predicate2 | Function | any; 547 | switch (predicateType) { 548 | case PredicateType.PREDICATE: 549 | p = nonPredicate(>predicate); 550 | break; 551 | case PredicateType.PREDICATE2: 552 | p = nonPredicate2(>predicate); 553 | break; 554 | case PredicateType.FUNCTION: 555 | p = (i1: any, i2: any) => { 556 | return !(predicate).call({}, i1, i2); 557 | }; 558 | break; 559 | } 560 | return p; 561 | } 562 | 563 | export class BooleanPredicate implements Predicate { 564 | private readonly value: boolean; 565 | 566 | constructor(value: boolean) { 567 | Preconditions.checkTrue(Types.isBoolean(value)); 568 | this.value = value; 569 | } 570 | 571 | test(i: any): boolean { 572 | return this.value; 573 | } 574 | } 575 | 576 | export function booleanPredicate(value: boolean): BooleanPredicate { 577 | return new BooleanPredicate(value); 578 | } 579 | 580 | export function truePredicate(): BooleanPredicate { 581 | return booleanPredicate(true); 582 | } 583 | 584 | export function falsePredicate(): BooleanPredicate { 585 | return booleanPredicate(false); 586 | } 587 | 588 | export function wrappedPredicate2(comparator: Comparator | Func2 | Function): Predicate2 { 589 | let comp: Comparator; 590 | if (comparator == null) { 591 | comp = new IsComparator(); 592 | } else if (Comparators.isComparator(comparator)) { 593 | comp = >comparator; 594 | } else { 595 | let funcType: FunctionType = judgeFuncType(comparator); 596 | Preconditions.checkTrue(funcType != FunctionType.UNKNOWN, "argument not a comparator or a function"); 597 | comp = new FunctionComparator(comparator); 598 | } 599 | return { 600 | test(e1: any, e2: any) { 601 | return comp.compare(e1, e2) == 0; 602 | } 603 | } 604 | } -------------------------------------------------------------------------------- /src/main/HashCodes.ts: -------------------------------------------------------------------------------- 1 | import * as Numbers from "./Numbers"; 2 | import * as Dates from "./Dates"; 3 | import * as Booleans from "./Booleans"; 4 | import * as Strings from "./Strings"; 5 | import * as Iterables from "./Iterables"; 6 | import * as Types from "./Types"; 7 | import {isEmpty} from "./Emptys"; 8 | import {Objects} from "./index"; 9 | 10 | Object.defineProperty(Object.prototype, "hashCode", { 11 | configurable: true, 12 | enumerable: false, 13 | writable: true, 14 | value: function () { 15 | return hashCode(this); 16 | } 17 | }); 18 | 19 | Date.prototype["hashCode"] = function () { 20 | return Dates.hashCode(this); 21 | }; 22 | 23 | Boolean.prototype["hashCode"] = function () { 24 | return Booleans.hashCode(this); 25 | }; 26 | 27 | String.prototype["hashCode"] = function () { 28 | return Strings.hashCode(this); 29 | }; 30 | 31 | Number.prototype["hashCode"] = function () { 32 | return Numbers.hashCode(this); 33 | }; 34 | 35 | Array.prototype["hashCode"] = function () { 36 | return Iterables.hashCode(this); 37 | }; 38 | 39 | Set.prototype["hashCode"] = function () { 40 | return Iterables.hashCode(this); 41 | }; 42 | Map.prototype["hashCode"] = function () { 43 | return Iterables.hashCode(this); 44 | }; 45 | 46 | 47 | export function hashCode(object: any) { 48 | if (isEmpty(object)) { 49 | return 0; 50 | } 51 | if (Types.isNumber(object)) { 52 | return Numbers.hashCode(object); 53 | } 54 | 55 | if (Types.isBoolean(object)) { 56 | return Booleans.hashCode(object); 57 | } 58 | 59 | if (Types.isString(object)) { 60 | return Strings.hashCode(object); 61 | } 62 | if (Types.isDate(object)) { 63 | return Dates.hashCode(object); 64 | } 65 | if( object instanceof Array || object instanceof Set || object instanceof Map || Types.isCollection(object) || Types.isMap(object)){ 66 | return Iterables.hashCode(object); 67 | } 68 | return hashCode(Objects.keys(object)); 69 | } 70 | 71 | -------------------------------------------------------------------------------- /src/main/Iterables.ts: -------------------------------------------------------------------------------- 1 | import * as Types from "./Types"; 2 | import * as Objects from "./Objects"; 3 | import * as Preconditions from "./Preconditions"; 4 | import * as Numbers from "./Numbers"; 5 | import * as Collects from "./Collects"; 6 | import * as Booleans from "./Booleans"; 7 | import * as Pipeline from "./Pipeline"; 8 | import {emptyArrayList} from "./Collects"; 9 | import {UnsupportOperationException} from "./Exceptions"; 10 | import {Comparator, HashedComparator, ObjectComparator} from "./Comparators"; 11 | import {Delegatable} from "./Delegatables"; 12 | import {binarySearch, SearchResult} from "./Algorithms"; 13 | 14 | export abstract class AbstractIterator implements Iterator { 15 | abstract next(...args: [] | [undefined]): IteratorResult; 16 | 17 | return(value?: any): IteratorResult { 18 | return { 19 | value: value, 20 | done: true 21 | }; 22 | } 23 | 24 | throw(e?: any): IteratorResult { 25 | if (Types.isError(e)) { 26 | throw e; 27 | } 28 | return { 29 | value: null, 30 | done: true 31 | } 32 | } 33 | } 34 | 35 | export enum ObjectPropertiesIterateType { 36 | KEY, 37 | VALUE, 38 | KEY_VALUE 39 | } 40 | 41 | export class ObjectPropertiesIterator extends AbstractIterator implements IterableIterator { 42 | private readonly obj: Object; 43 | private keysIter: Iterator; 44 | private readonly iterateType: ObjectPropertiesIterateType; 45 | 46 | constructor(object: Object, iterateType?: ObjectPropertiesIterateType) { 47 | super(); 48 | this.obj = object; 49 | this.keysIter = new ArrayList(Object.keys(object))[Symbol.iterator](); 50 | if (iterateType == null) { 51 | iterateType = ObjectPropertiesIterateType.KEY_VALUE; 52 | } 53 | this.iterateType = iterateType; 54 | } 55 | 56 | [Symbol.iterator](): IterableIterator { 57 | return this; 58 | } 59 | 60 | next(...args: [] | [undefined]): IteratorResult { 61 | let keyResult: IteratorResult = this.keysIter.next(); 62 | let value: any; 63 | switch (this.iterateType) { 64 | case ObjectPropertiesIterateType.KEY: 65 | value = keyResult.value; 66 | break; 67 | case ObjectPropertiesIterateType.VALUE: 68 | value = this.obj[keyResult.value]; 69 | break; 70 | default: 71 | value = { 72 | key: keyResult.value, 73 | value: this.obj[keyResult.value] 74 | }; 75 | } 76 | return { 77 | value: value, 78 | done: keyResult.done 79 | }; 80 | } 81 | 82 | } 83 | 84 | export class NullIterable implements Iterable { 85 | [Symbol.iterator](): Iterator { 86 | return new NullIterator(); 87 | } 88 | } 89 | 90 | export class NullIterator extends AbstractIterator { 91 | next(...args: [] | [undefined]): IteratorResult { 92 | return { 93 | done: true, 94 | value: undefined 95 | }; 96 | } 97 | } 98 | 99 | export class NoopIterator extends NullIterator { 100 | } 101 | 102 | 103 | export interface Collection extends Iterable { 104 | add(e: E): boolean; 105 | 106 | addAll(c: Iterable): boolean; 107 | 108 | clear(): void; 109 | 110 | contains(e: E): boolean; 111 | 112 | containsAll(c: Collection): boolean; 113 | 114 | [Symbol.iterator](): Iterator; 115 | 116 | remove(e: E): E; 117 | 118 | removeAll(c: Collection): boolean; 119 | 120 | retainAll(c: Collection): boolean; 121 | 122 | size(): number; 123 | 124 | isEmpty(): boolean; 125 | 126 | toArray(array?: Array): Array; 127 | 128 | hashCode(): number; 129 | } 130 | 131 | export type LinearCollection = Collection | Set | Array; 132 | 133 | export abstract class AbstractCollection implements Collection { 134 | 135 | abstract add(e: E): boolean ; 136 | 137 | addAll(c: Iterable): boolean { 138 | let result: boolean = true; 139 | for (let e of c) { 140 | if (!this.add(e)) { 141 | result = false; 142 | } 143 | } 144 | return result; 145 | } 146 | 147 | abstract clear(); 148 | 149 | abstract contains(e: E): boolean ; 150 | 151 | containsAll(c: Collection): boolean { 152 | for (let e of c) { 153 | if (!this.contains(e)) { 154 | return false; 155 | } 156 | } 157 | return true; 158 | } 159 | 160 | removeAll(c: Collection): boolean { 161 | let result: boolean = true; 162 | for (let e of c) { 163 | if (!this.remove(e)) { 164 | result = false; 165 | } 166 | } 167 | return result; 168 | } 169 | 170 | abstract retainAll(c: Collection): boolean; 171 | 172 | 173 | abstract remove(e: E): E; 174 | 175 | abstract toArray(array?: Array): Array; 176 | 177 | isEmpty(): boolean { 178 | return this.size() == 0; 179 | } 180 | 181 | size(): number { 182 | return 0; 183 | } 184 | 185 | abstract [Symbol.iterator](): Iterator ; 186 | 187 | hashCode(): number { 188 | return hashCode(this); 189 | } 190 | } 191 | 192 | export interface List extends Collection { 193 | get(index: number): E; 194 | 195 | set(index: number, e: E): E; 196 | 197 | removeByIndex(index: number); 198 | 199 | indexOf(e: E): number; 200 | 201 | lastIndexOf(e: E): number; 202 | 203 | subList(fromIndex: number, toIndex: number); 204 | } 205 | 206 | export abstract class AbstractList extends AbstractCollection implements List { 207 | protected length: number = 0; 208 | 209 | 210 | abstract add(e: E, index?: number): boolean; 211 | 212 | abstract get(index: number): E; 213 | 214 | abstract set(index: number, e: E): E; 215 | 216 | abstract subList(fromIndex: number, toIndex: number) ; 217 | 218 | contains(e: E): boolean { 219 | return this.indexOf(e) != -1; 220 | } 221 | 222 | size(): number { 223 | return this.length; 224 | } 225 | 226 | abstract lastIndexOf(e: E): number ; 227 | 228 | abstract indexOf(e: E): number; 229 | 230 | removeByIndex(index: number) { 231 | if (index < 0 || index >= this.size()) { 232 | return; 233 | } 234 | } 235 | 236 | 237 | } 238 | 239 | export class ArrayList extends AbstractList { 240 | private array: Array = []; 241 | 242 | new(): ArrayList { 243 | return new ArrayList(); 244 | }; 245 | 246 | constructor(arraylist?: Collection | Array | Set | Iterable | IterableIterator | undefined | null) { 247 | super(); 248 | if (arraylist == null) { 249 | this.array = []; 250 | } else { 251 | if (Types.isArray(arraylist)) { 252 | this.array = >arraylist; 253 | } else { 254 | this.array = new Array(); 255 | this.addAll(arraylist); 256 | } 257 | } 258 | this.length = this.array.length; 259 | } 260 | 261 | get(index: number): E { 262 | Preconditions.checkIndex(index >= 0 && index < this.length); 263 | return this.array[index]; 264 | } 265 | 266 | set(index: number, e: E): E { 267 | let oldValue: E = this.get(index); 268 | this.array[index] = e; 269 | return oldValue; 270 | } 271 | 272 | indexOf(e: E): number { 273 | let e0; 274 | for (let i = 0; i < this.size(); i++) { 275 | e0 = this.get(i); 276 | if (e0 == e) { 277 | return i; 278 | } 279 | } 280 | return -1; 281 | } 282 | 283 | lastIndexOf(e: E): number { 284 | let e0; 285 | for (let i = this.size(); i >= 0; i--) { 286 | e0 = this.get(i); 287 | if (e0 == e) { 288 | return i; 289 | } 290 | } 291 | return -1; 292 | } 293 | 294 | subList(fromIndex: number, toIndex: number) { 295 | Preconditions.checkTrue(fromIndex >= toIndex); 296 | let result = new ArrayList(); 297 | let i = fromIndex; 298 | while (i < toIndex) { 299 | result.add(this.get(i)); 300 | i++; 301 | } 302 | return result; 303 | } 304 | 305 | add(e: E, index?: number): boolean { 306 | if (index == null || index >= this.length) { 307 | this.array.push(e); 308 | } else if (index < 0) { 309 | this.array.unshift(e); 310 | } else { 311 | this.array.splice(index, 0, e); 312 | } 313 | this.length++; 314 | return true; 315 | } 316 | 317 | clear(): void { 318 | if (this.length > 0) { 319 | this.array.splice(0); 320 | } 321 | this.length = 0; 322 | } 323 | 324 | remove(e: E): E { 325 | let newArray: Array = []; 326 | for (let e0 of this.array) { 327 | if (e0 != e) { 328 | newArray.push(e0); 329 | } 330 | } 331 | this.array = newArray; 332 | this.length = this.array.length; 333 | return e; 334 | } 335 | 336 | retainAll(c: Collection): boolean { 337 | let newArray: Array = []; 338 | let containAll: boolean = true; 339 | for (let e of this.array) { 340 | if (c.contains(e)) { 341 | newArray.push(e); 342 | } else { 343 | containAll = false; 344 | } 345 | } 346 | this.array = newArray; 347 | this.length = this.array.length; 348 | return containAll; 349 | } 350 | 351 | toArray(array?: Array): Array { 352 | if (array == null) { 353 | return this.array; 354 | } 355 | array.concat(this.array); 356 | return array; 357 | } 358 | 359 | [Symbol.iterator](): Iterator { 360 | return new ArrayListIterator(this); 361 | } 362 | 363 | 364 | removeByIndex(index: number) { 365 | if (index < 0 || index >= this.size()) { 366 | return; 367 | } 368 | this.array.splice(index, 1); 369 | this.length--; 370 | } 371 | } 372 | 373 | export class ArrayListIterator extends AbstractIterator { 374 | private index: number = 0; 375 | private array: ArrayList; 376 | 377 | constructor(array: ArrayList) { 378 | super(); 379 | this.array = array; 380 | } 381 | 382 | next(...args: [] | [undefined]): IteratorResult { 383 | if (this.index < this.array.size()) { 384 | return { 385 | value: this.array.get(this.index++), 386 | done: false 387 | }; 388 | } else { 389 | return { 390 | done: true, 391 | value: null 392 | }; 393 | } 394 | } 395 | 396 | } 397 | 398 | interface LinkedListNode { 399 | e: E; 400 | next: LinkedListNode; 401 | prev: LinkedListNode; 402 | } 403 | 404 | export class LinkedList extends AbstractList { 405 | first: LinkedListNode; 406 | last: LinkedListNode; 407 | 408 | constructor(c?: Collection | Array | Set | Iterable | IterableIterator | undefined | null) { 409 | super(); 410 | this.first = this.last = >Objects.unknownNull(); 411 | if (c != null) { 412 | this.addAll(new ArrayList(c)) 413 | } 414 | } 415 | 416 | clear() { 417 | this.last = this.first = >Objects.unknownNull(); 418 | this.length = 0 419 | } 420 | 421 | get(index: number): E { 422 | let node: LinkedListNode = this.getNode(index); 423 | if (node != null) { 424 | return node.e; 425 | } 426 | return Objects.unknownNull(); 427 | } 428 | 429 | indexOf(e: E): number { 430 | let i: number = 0; 431 | let node: LinkedListNode = this.first; 432 | while (i < this.length) { 433 | if (node != null) { 434 | if (node.e != e) { 435 | node = node.next; 436 | } else { 437 | return i; 438 | } 439 | } 440 | i++; 441 | } 442 | return -1; 443 | } 444 | 445 | lastIndexOf(e: E): number { 446 | let i: number = this.length - 1; 447 | let node: LinkedListNode = this.last; 448 | while (i >= 0) { 449 | if (node != null) { 450 | if (node.e != e) { 451 | node = node.prev; 452 | } else { 453 | return i; 454 | } 455 | } 456 | i++; 457 | } 458 | return -1; 459 | } 460 | 461 | [Symbol.iterator](): Iterator { 462 | return new LinkedListIterator(this); 463 | } 464 | 465 | remove(e: E): E { 466 | let node: LinkedListNode = this.first; 467 | while (node != null) { 468 | if (node.e == e) { 469 | this.removeNode(node); 470 | } 471 | node = node.next; 472 | } 473 | return e; 474 | } 475 | 476 | 477 | removeByIndex(index: number) { 478 | if (index < 0 || index >= this.size()) { 479 | return; 480 | } 481 | let node: LinkedListNode = this.getNode(index); 482 | this.removeNode(node); 483 | } 484 | 485 | retainAll(c: Collection): boolean { 486 | let node: LinkedListNode = this.first; 487 | while (node != null) { 488 | if (!c.contains(node.e)) { 489 | this.removeNode(node); 490 | } 491 | node = node.next; 492 | } 493 | return false; 494 | } 495 | 496 | private removeNode(node: LinkedListNode): void { 497 | Preconditions.checkNonNull(node); 498 | let prev: LinkedListNode = node.prev; 499 | if (prev != null) { 500 | prev.next = node.next; 501 | } 502 | if (node.next != null) { 503 | node.next.prev = prev; 504 | } 505 | if (this.last == node) { 506 | this.last = prev; 507 | } 508 | if (this.first == node) { 509 | this.first = node.next 510 | } 511 | this.length--; 512 | } 513 | 514 | private getNode(index: number): LinkedListNode { 515 | Preconditions.checkTrue(index >= 0 && index < this.length); 516 | let node; 517 | if (index < this.length >> 1) { 518 | // loop from the first node 519 | let i: number = 0; 520 | node = this.first; 521 | while (i < index) { 522 | node = node.next; 523 | i++; 524 | } 525 | } else { 526 | // loop from the last node 527 | let i: number = this.length - 1; 528 | node = this.last; 529 | while (i > index) { 530 | node = node.prev 531 | i--; 532 | } 533 | } 534 | return node; 535 | } 536 | 537 | set(index: number, e: E): E { 538 | let oldNode: LinkedListNode = this.getNode(index); 539 | let oldValue = oldNode.e; 540 | if (oldNode != null) { 541 | oldNode.e = e; 542 | } 543 | return oldValue; 544 | } 545 | 546 | subList(fromIndex: number, toIndex: number) { 547 | if (fromIndex < 0) { 548 | fromIndex = 0; 549 | } 550 | if (fromIndex >= this.length) { 551 | return new LinkedList(); 552 | } 553 | if (toIndex > this.length) { 554 | toIndex = this.length; 555 | } 556 | 557 | let node: LinkedListNode = this.getNode(fromIndex); 558 | let array: ArrayList = new ArrayList(); 559 | array.add(node.e); 560 | fromIndex++; 561 | while (fromIndex < toIndex) { 562 | node = node.next; 563 | array.add(node.e); 564 | } 565 | return new LinkedList(array); 566 | } 567 | 568 | add(e: E, index?: number): boolean { 569 | if (index == null || index >= this.length) { 570 | let newNode: LinkedListNode = { 571 | e: e, 572 | prev: this.last, 573 | next: >Objects.unknownNull() 574 | }; 575 | 576 | if (this.last != null) { 577 | this.last.next = newNode; 578 | } 579 | this.last = newNode; 580 | if (this.first == null) { 581 | this.first = this.last; 582 | } 583 | } else if (index <= 0) { 584 | let newNode: LinkedListNode = { 585 | e: e, 586 | prev: >Objects.unknownNull(), 587 | next: this.first 588 | }; 589 | if (this.first != null) { 590 | this.first.prev = newNode; 591 | } 592 | this.first = newNode; 593 | if (this.last == null) { 594 | this.last = this.first; 595 | } 596 | } else { 597 | let next: LinkedListNode = this.getNode(index); 598 | let prev = next != null ? next.prev : >Objects.unknownNull(); 599 | 600 | let newNode: LinkedListNode = { 601 | e: e, 602 | prev: prev, 603 | next: next 604 | }; 605 | if (prev != null) { 606 | prev.next = newNode; 607 | } 608 | if (next != null) { 609 | next.prev = newNode; 610 | } 611 | } 612 | 613 | this.length++; 614 | return true; 615 | } 616 | 617 | toArray(array?: Array): Array { 618 | let arr = array == null ? [] : array; 619 | for (let element of this) { 620 | arr.push(element); 621 | } 622 | return arr 623 | } 624 | 625 | } 626 | 627 | export class LinkedListIterator extends AbstractIterator { 628 | private node: LinkedListNode; 629 | 630 | constructor(list: LinkedList) { 631 | super(); 632 | this.node = list.first; 633 | } 634 | 635 | next(...args: [] | [undefined]): IteratorResult { 636 | if (this.node != null) { 637 | let n = this.node; 638 | this.node = n.next; 639 | return { 640 | value: n.e, 641 | done: false 642 | } 643 | } 644 | return { 645 | done: true, 646 | value: null 647 | } 648 | } 649 | 650 | } 651 | 652 | export interface LikeJavaSet extends Collection { 653 | 654 | } 655 | 656 | export abstract class AbstractSet extends AbstractCollection implements LikeJavaSet { 657 | abstract add(e?: E): boolean; 658 | 659 | abstract size(): number; 660 | 661 | abstract clear(): void; 662 | 663 | abstract contains(e: E): boolean; 664 | 665 | abstract [Symbol.iterator](): Iterator; 666 | 667 | abstract remove(e: E): E; 668 | 669 | abstract retainAll(c: Collection): boolean; 670 | 671 | abstract toArray(array?: Array): Array; 672 | } 673 | 674 | abstract class AbstractMapBasedSet extends AbstractSet { 675 | protected map: LikeJavaMap; 676 | 677 | constructor() { 678 | super(); 679 | this.map = >Objects.unknownNull(); 680 | } 681 | 682 | add(e?: E): boolean { 683 | if (e == null) { 684 | return false; 685 | } 686 | if (this.map.containsKey(e)) { 687 | return false; 688 | } 689 | this.map.put(e, null); 690 | return true; 691 | } 692 | 693 | size(): number { 694 | return this.map.size(); 695 | } 696 | 697 | clear(): void { 698 | this.map.clear(); 699 | } 700 | 701 | contains(e: E): boolean { 702 | return this.map.containsKey(e); 703 | } 704 | 705 | [Symbol.iterator](): Iterator { 706 | return this.map.keySet()[Symbol.iterator](); 707 | } 708 | 709 | remove(e: E): E { 710 | this.map.remove(e); 711 | return e; 712 | } 713 | 714 | retainAll(c: Collection): boolean { 715 | let removed: ArrayList = new ArrayList(); 716 | for (let element of this.toArray()) { 717 | if (element != null && !c.contains(element)) { 718 | removed.add(element); 719 | } 720 | } 721 | this.removeAll(removed); 722 | return true; 723 | } 724 | 725 | toArray(array?: Array): Array { 726 | if (array == null) { 727 | return Collects.toArray(this.map.keySet()); 728 | } 729 | array.push(...this.map.keySet()); 730 | return array; 731 | } 732 | 733 | } 734 | 735 | export class HashSet extends AbstractMapBasedSet { 736 | 737 | constructor(list?: Collection | Array | Set | Iterable | IterableIterator | undefined | null) { 738 | super(); 739 | this.map = new HashMap(); 740 | if (list != null) { 741 | if (list instanceof AbstractCollection) { 742 | this.addAll(list); 743 | } else { 744 | for (let element of list) { 745 | this.add(element); 746 | } 747 | } 748 | } 749 | } 750 | } 751 | 752 | export class LinkedHashSet extends AbstractMapBasedSet { 753 | 754 | constructor(list?: Collection | Array | Set | Iterable | IterableIterator | undefined | null) { 755 | super(); 756 | this.map = new LinkedHashMap(); 757 | if (list != null) { 758 | if (list instanceof AbstractCollection) { 759 | this.addAll(list); 760 | } else { 761 | for (let element of list) { 762 | this.add(element); 763 | } 764 | } 765 | } 766 | } 767 | } 768 | 769 | export class TreeSet extends AbstractMapBasedSet { 770 | 771 | constructor(list?: Collection | Array | Set | Iterable | IterableIterator | undefined | null, comparator?: Comparator) { 772 | super(); 773 | this.map = new TreeMap(>Objects.unknownNull(), comparator); 774 | if (list != null) { 775 | if (list instanceof AbstractCollection) { 776 | this.addAll(list); 777 | } else { 778 | for (let element of list) { 779 | this.add(element); 780 | } 781 | } 782 | } 783 | } 784 | 785 | getComparator(): Comparator { 786 | return (>this.map).getComparator(); 787 | } 788 | 789 | setComparator(comparator: Comparator): void { 790 | (>this.map).setComparator(comparator); 791 | } 792 | 793 | } 794 | 795 | 796 | export interface MapEntry { 797 | key: K; 798 | value?: V; 799 | 800 | hashCode(): number; 801 | } 802 | 803 | export function isLikeMapEntry(obj: object) { 804 | if (Objects.isNull(obj)) { 805 | return false; 806 | } 807 | return Objects.hasProperty(obj, "key") && Objects.hasProperty(obj, "value"); 808 | } 809 | 810 | export function toMapEntry(object): MapEntry | null { 811 | if (isLikeMapEntry(object)) { 812 | return null; 813 | } 814 | return new SimpleMapEntry(object["key"], object["value"]); 815 | } 816 | 817 | export class MapEntryKeyComparator implements Comparator>, Delegatable> { 818 | private keyComparator: Comparator; 819 | 820 | constructor(keyComparator?: Comparator) { 821 | this.keyComparator = keyComparator == null ? new HashedComparator() : keyComparator; 822 | } 823 | 824 | compare(e1: MapEntry, e2: MapEntry): number { 825 | return this.keyComparator.compare(e1.key, e2.key); 826 | } 827 | 828 | setDelegate(keyComparator: Comparator): void { 829 | this.keyComparator = keyComparator == null ? new HashedComparator() : keyComparator; 830 | } 831 | 832 | getDelegate(): Comparator { 833 | return this.keyComparator; 834 | } 835 | } 836 | 837 | export class SimpleMapEntry implements MapEntry { 838 | key: K; 839 | value?: V; 840 | 841 | constructor(key: K, value?: V) { 842 | this.key = key; 843 | this.value = value; 844 | } 845 | 846 | hashCode(): number { 847 | return (this.key == null ? 0 : Objects.hashCode(this.key)) ^ 848 | (this.value == null ? 0 : Objects.hashCode(this.value)); 849 | } 850 | } 851 | 852 | 853 | export interface LikeJavaMap extends Iterable> { 854 | clear(): void; 855 | 856 | containsKey(key: K): boolean; 857 | 858 | containsValue(value: V): boolean; 859 | 860 | get(key: K): V; 861 | 862 | keySet(): LikeJavaSet; 863 | 864 | values(): Collection; 865 | 866 | entrySet(): LikeJavaSet>; 867 | 868 | put(key: K, value: V): V | undefined; 869 | 870 | putAll(map: LikeJavaMap): void; 871 | 872 | remove(key: K): V | undefined; 873 | 874 | isEmpty(): boolean; 875 | 876 | size(): number; 877 | 878 | [Symbol.iterator](): Iterator>; 879 | 880 | hashCode(): number; 881 | } 882 | 883 | export abstract class AbstractMap implements LikeJavaMap { 884 | abstract size(): number; 885 | 886 | isEmpty(): boolean { 887 | return this.size() == 0; 888 | } 889 | 890 | abstract clear(): void; 891 | 892 | abstract containsKey(key: K): boolean; 893 | 894 | abstract containsValue(value: V): boolean; 895 | 896 | abstract get(key: K): V; 897 | 898 | abstract keySet(): LikeJavaSet; 899 | 900 | abstract values(): Collection; 901 | 902 | abstract entrySet(): LikeJavaSet>; 903 | 904 | abstract put(key?: K, value?: V): V | undefined; 905 | 906 | putAll(map: LikeJavaMap): void { 907 | if (map != null) { 908 | for (let entry of map) { 909 | this.put(entry.key, entry.value); 910 | } 911 | } 912 | } 913 | 914 | abstract remove(key: K): V | undefined; 915 | 916 | abstract [Symbol.iterator](): Iterator>; 917 | 918 | hashCode(): number { 919 | return hashCode(this); 920 | } 921 | } 922 | 923 | export class TreeMap extends AbstractMap { 924 | private readonly list: ArrayList> = new ArrayList>(); 925 | private readonly map: HashMap = new HashMap(); 926 | private comparator: MapEntryKeyComparator = >Objects.unknownNull(); 927 | 928 | 929 | constructor(map?: LikeJavaMap | Map | undefined | null, comparator?: Comparator) { 930 | super(); 931 | if (map != null) { 932 | if (map instanceof Map) { 933 | this.comparator = new MapEntryKeyComparator(comparator); 934 | for (let entry of map.entries()) { 935 | this.put(entry[0], entry[1]); 936 | } 937 | } else if (map instanceof AbstractMap) { 938 | if (map instanceof TreeMap) { 939 | this.comparator = new MapEntryKeyComparator((>map).getComparator()); 940 | } 941 | if (this.comparator == null) { 942 | this.comparator = new MapEntryKeyComparator(new ObjectComparator()); 943 | } 944 | this.putAll(map); 945 | } 946 | } 947 | if (this.comparator == null) { 948 | this.comparator = new MapEntryKeyComparator(new ObjectComparator()); 949 | } 950 | } 951 | 952 | getComparator(): Comparator { 953 | return this.comparator.getDelegate(); 954 | } 955 | 956 | setComparator(comparator: Comparator): void { 957 | this.comparator.setDelegate(comparator); 958 | } 959 | 960 | [Symbol.iterator](): Iterator> { 961 | return this.list[Symbol.iterator](); 962 | } 963 | 964 | clear(): void { 965 | this.list.clear(); 966 | this.map.clear(); 967 | } 968 | 969 | containsKey(key: K): boolean { 970 | return this.map.containsKey(key); 971 | } 972 | 973 | containsValue(value: V): boolean { 974 | return this.map.containsValue(value); 975 | } 976 | 977 | entrySet(): LikeJavaSet> { 978 | return >>new MapInnerEntrySet(this.map, this.list); 979 | } 980 | 981 | get(key: K): V { 982 | return this.map.get(key); 983 | } 984 | 985 | keySet(): LikeJavaSet { 986 | return new MapInnerKeySet(this, Pipeline.of(this.list).map((item: MapEntry) => { 987 | return item.key; 988 | }).asList()); 989 | } 990 | 991 | put(key: K, value?: V): V | undefined { 992 | if (key == null) { 993 | return value; 994 | } 995 | let newEntry: MapEntry = new SimpleMapEntry(key, value); 996 | let searchResult: SearchResult> = binarySearch(this.list, newEntry, this.comparator, true, 0, this.list.size() - 1); 997 | let oldValue: V; 998 | if (searchResult.value != null) { 999 | let entry: MapEntry = searchResult.value; 1000 | oldValue = entry.value == null ? Objects.unknownNull() : entry.value; 1001 | entry.value = value; 1002 | } else { 1003 | oldValue = Objects.unknownNull(); 1004 | this.list.add(newEntry, searchResult.index); 1005 | } 1006 | this.map.put(key, value); 1007 | return oldValue; 1008 | } 1009 | 1010 | remove(key: K): V | undefined { 1011 | let newEntry: MapEntry = new SimpleMapEntry(key, Objects.unknownNull()); 1012 | let searchResult: SearchResult> = binarySearch(this.list, newEntry, this.comparator, true, 0, this.list.size() - 1); 1013 | let value: V = Objects.unknownNull(); 1014 | if (searchResult.value != null) { 1015 | value = this.map.remove(key); 1016 | this.list.removeByIndex(searchResult.index); 1017 | } 1018 | return value; 1019 | } 1020 | 1021 | size(): number { 1022 | return this.list.size(); 1023 | } 1024 | 1025 | values(): Collection { 1026 | return Pipeline.of(this.list).map((entry: MapEntry) => { 1027 | return entry.value; 1028 | }).asList(); 1029 | } 1030 | 1031 | } 1032 | 1033 | 1034 | export class HashMap extends AbstractMap { 1035 | protected length: number = 0; 1036 | protected array: Array>> = []; 1037 | private readonly MAX_SLOT: number = 48; 1038 | 1039 | constructor(map?: LikeJavaMap | Map | undefined | null) { 1040 | super(); 1041 | if (map != null) { 1042 | if (this instanceof Map) { 1043 | for (let [key, value] of >map) { 1044 | this.put(key, value); 1045 | } 1046 | } else { 1047 | this.putAll(>map); 1048 | } 1049 | } 1050 | } 1051 | 1052 | clear(): void { 1053 | for (let list of this.array) { 1054 | if (list != null) { 1055 | list.clear(); 1056 | } 1057 | } 1058 | this.length = 0; 1059 | } 1060 | 1061 | containsKey(key: K): boolean { 1062 | let entries: List> = this.getKeySlotList(key); 1063 | return Collects.anyMatch(entries, { 1064 | test(entry: MapEntry) { 1065 | return entry.key == key; 1066 | } 1067 | }); 1068 | } 1069 | 1070 | private getKeySlot(key: K): number { 1071 | let keyHash: number = Numbers.parseInt(Objects.hashCode(key)); 1072 | return keyHash % this.MAX_SLOT; 1073 | } 1074 | 1075 | private getKeySlotList(key: K): List> { 1076 | let keySlot: number = this.getKeySlot(key); 1077 | if (this.array[keySlot] == null) { 1078 | this.array[keySlot] = new LinkedList>(); 1079 | } 1080 | return this.array[keySlot]; 1081 | } 1082 | 1083 | containsValue(value: V): boolean { 1084 | return Collects.anyMatch(this.values(), { 1085 | test(v: V) { 1086 | return v == value; 1087 | } 1088 | }); 1089 | } 1090 | 1091 | entrySet(): LikeJavaSet> { 1092 | return >>new MapInnerEntrySet(this, Pipeline.of(this.array).flatMap().asList()); 1093 | } 1094 | 1095 | get(key: K): V { 1096 | const list: List> = this.getKeySlotList(key); 1097 | return Pipeline.of(list).findFirst({ 1098 | test: function (entry: MapEntry) { 1099 | return key == entry.key; 1100 | } 1101 | }); 1102 | } 1103 | 1104 | 1105 | keySet(): LikeJavaSet { 1106 | return new MapInnerKeySet(this, Pipeline.of(this.array).flatMap({ 1107 | apply(entry: MapEntry): K { 1108 | return entry.key; 1109 | } 1110 | }).asList()); 1111 | } 1112 | 1113 | put(key: K, value?: V): V | undefined { 1114 | return this.putEntry(new SimpleMapEntry(key, value)); 1115 | } 1116 | 1117 | protected putEntry(entry: MapEntry): V | undefined { 1118 | if (entry == null || entry.key == null) { 1119 | return undefined; 1120 | } 1121 | let key = entry.key; 1122 | let value = entry.value; 1123 | let list: List> = this.getKeySlotList(key); 1124 | let oldEntry: MapEntry = Pipeline.of(list).findFirst({ 1125 | test: function (entry: MapEntry) { 1126 | return key == entry.key; 1127 | } 1128 | }); 1129 | if (oldEntry == null) { 1130 | list.add(entry); 1131 | this.length++; 1132 | return undefined; 1133 | } else { 1134 | oldEntry.value = value; 1135 | return oldEntry.value; 1136 | } 1137 | } 1138 | 1139 | putAll(map: LikeJavaMap): void { 1140 | if (map != null) { 1141 | for (let entry of map.entrySet()) { 1142 | this.put(entry.key, entry.value); 1143 | } 1144 | } 1145 | } 1146 | 1147 | remove(key: K): V | undefined { 1148 | if (key == null) { 1149 | return undefined; 1150 | } 1151 | 1152 | let list: List> = this.getKeySlotList(key); 1153 | let oldEntry: MapEntry = Pipeline.of(list).findFirst({ 1154 | test: function (entry: MapEntry) { 1155 | return key == entry.key; 1156 | } 1157 | }); 1158 | if (oldEntry == null) { 1159 | return undefined; 1160 | } else { 1161 | let result = oldEntry.value; 1162 | Collects.removeIf(list, { 1163 | test(entry: MapEntry) { 1164 | return entry.key == key; 1165 | } 1166 | }); 1167 | this.length--; 1168 | return result; 1169 | } 1170 | } 1171 | 1172 | size(): number { 1173 | return this.length; 1174 | } 1175 | 1176 | values(): Collection { 1177 | return Pipeline.of(this.array).flatMap({ 1178 | apply(entry: MapEntry): V { 1179 | return entry.value == null ? Objects.unknownNull() : entry.value; 1180 | } 1181 | }).asList(); 1182 | } 1183 | 1184 | 1185 | [Symbol.iterator](): Iterator> { 1186 | return new ArrayList(this.entrySet())[Symbol.iterator](); 1187 | } 1188 | } 1189 | 1190 | 1191 | export class LinkedHashMap extends HashMap { 1192 | private readonly orders: List> = new ArrayList>(); 1193 | 1194 | constructor(map?: LikeJavaMap | Map | undefined | null) { 1195 | super(map); 1196 | } 1197 | 1198 | clear(): void { 1199 | super.clear(); 1200 | this.orders.clear(); 1201 | } 1202 | 1203 | entrySet(): LikeJavaSet> { 1204 | return >>new MapInnerEntrySet(this, this.orders); 1205 | } 1206 | 1207 | keySet(): LikeJavaSet { 1208 | return new MapInnerKeySet(this, Pipeline.of(this.orders).map({ 1209 | apply(entry: MapEntry): K { 1210 | return entry.key; 1211 | } 1212 | }).asList()); 1213 | } 1214 | 1215 | put(key: K, value?: V): V | undefined { 1216 | if (key == null) { 1217 | return undefined; 1218 | } 1219 | let entry: MapEntry = new SimpleMapEntry(key, value); 1220 | let oldSize = this.size(); 1221 | let oldValue = this.putEntry(entry); 1222 | if (this.size() > oldSize) { 1223 | this.orders.add(entry); 1224 | } else { 1225 | let entry: MapEntry = Collects.findFirst(this.orders, { 1226 | test(index: number, entry: MapEntry) { 1227 | return entry != null && entry.key == key; 1228 | } 1229 | }); 1230 | if (entry != null) { 1231 | entry.value = value; 1232 | } 1233 | } 1234 | return oldValue; 1235 | } 1236 | 1237 | 1238 | remove(key: K): V | undefined { 1239 | let oldSize = this.size(); 1240 | let value = super.remove(key); 1241 | if (this.size() < oldSize) { 1242 | Collects.removeIf(this.orders, { 1243 | test(index: number, entry: MapEntry) { 1244 | return entry != null && entry.key == key; 1245 | } 1246 | }) 1247 | } 1248 | return value; 1249 | } 1250 | 1251 | values(): Collection { 1252 | return Pipeline.of(this.orders).map({ 1253 | apply(entry: MapEntry): V { 1254 | return entry.value == null ? Objects.unknownNull() : entry.value; 1255 | } 1256 | }).asList(); 1257 | } 1258 | 1259 | [Symbol.iterator](): Iterator> { 1260 | return new ArrayList(this.entrySet())[Symbol.iterator](); 1261 | } 1262 | } 1263 | 1264 | class MapInnerEntrySet extends AbstractSet> { 1265 | private readonly map: LikeJavaMap; 1266 | private readonly entries: List>; 1267 | 1268 | constructor(map: LikeJavaMap, entries: List>) { 1269 | super(); 1270 | this.map = map; 1271 | this.entries = entries; 1272 | } 1273 | 1274 | [Symbol.iterator](): Iterator> { 1275 | return this.entries[Symbol.iterator](); 1276 | } 1277 | 1278 | add(e: MapEntry): boolean { 1279 | let size0 = this.map.size(); 1280 | this.map.put(e.key, e.value == null ? Objects.unknownNull() : e.value); 1281 | if (this.map.size() - size0 > 0) { 1282 | this.entries.add(e); 1283 | return true; 1284 | } 1285 | return false; 1286 | } 1287 | 1288 | clear() { 1289 | this.map.clear(); 1290 | this.entries.clear(); 1291 | } 1292 | 1293 | contains(e: MapEntry): boolean { 1294 | return this.entries.contains(e); 1295 | } 1296 | 1297 | remove(e: MapEntry): MapEntry { 1298 | this.entries.remove(e); 1299 | this.map.remove(e.key); 1300 | return e; 1301 | } 1302 | 1303 | retainAll(c: Collection>): boolean { 1304 | return false; 1305 | } 1306 | 1307 | toArray(array?: Array>): Array> { 1308 | return this.entries.toArray(array); 1309 | } 1310 | 1311 | size(): number { 1312 | return this.entries.size(); 1313 | } 1314 | 1315 | } 1316 | 1317 | class MapInnerKeySet extends AbstractSet { 1318 | private readonly map: LikeJavaMap; 1319 | private readonly keys: List; 1320 | 1321 | constructor(map: LikeJavaMap, keys: List) { 1322 | super(); 1323 | this.map = map; 1324 | this.keys = keys; 1325 | } 1326 | 1327 | [Symbol.iterator](): Iterator { 1328 | return this.keys[Symbol.iterator](); 1329 | } 1330 | 1331 | add(e: E): boolean { 1332 | throw new UnsupportOperationException(); 1333 | } 1334 | 1335 | clear() { 1336 | this.keys.clear(); 1337 | this.map.clear(); 1338 | } 1339 | 1340 | contains(e: E): boolean { 1341 | return this.map.containsKey(e); 1342 | } 1343 | 1344 | remove(e: E): E { 1345 | this.map.remove(e); 1346 | return this.keys.remove(e); 1347 | } 1348 | 1349 | retainAll(c: Collection): boolean { 1350 | let removed: Array = []; 1351 | for (let key of this.keys) { 1352 | if (!c.contains(key)) { 1353 | removed.push(key); 1354 | } 1355 | } 1356 | for (let key of removed) { 1357 | this.remove(key); 1358 | } 1359 | return true; 1360 | } 1361 | 1362 | toArray(array?: Array): Array { 1363 | return this.keys.toArray(array); 1364 | } 1365 | 1366 | size(): number { 1367 | return this.keys.size(); 1368 | } 1369 | } 1370 | 1371 | export function isIterator(obj: any): boolean { 1372 | if (obj != null) { 1373 | if (!Objects.hasProperty(obj, "next")) { 1374 | return false; 1375 | } 1376 | if (Types.isFunction(obj["next"])) { 1377 | let throwType = Types.getType(obj["throw"]); 1378 | let returnType = Types.getType(obj["return"]); 1379 | if (throwType != Function || throwType != undefined) { 1380 | return false; 1381 | } 1382 | if (returnType != Function || returnType != undefined) { 1383 | return false; 1384 | } 1385 | return true; 1386 | } 1387 | } 1388 | return false; 1389 | } 1390 | 1391 | export function isIterable(obj: any): boolean { 1392 | if (obj == null) { 1393 | return false; 1394 | } 1395 | if (Types.isCollection(obj) || obj instanceof AbstractMap || Types.isFunction(obj[Symbol.iterator])) { 1396 | return true; 1397 | } 1398 | return false; 1399 | } 1400 | 1401 | export function propertiesAsIterable(object: any) { 1402 | if (Types.isSimpleObject(object)) { 1403 | object[Symbol.iterator] = function (): IterableIterator { 1404 | return new ObjectPropertiesIterator(object); 1405 | } 1406 | } 1407 | return asIterable(object); 1408 | } 1409 | 1410 | 1411 | export function asIterable(object: any): Iterable { 1412 | if (object == null) { 1413 | return Collects.emptyArrayList(); 1414 | } 1415 | 1416 | if (isIterable(object)) { 1417 | return object; 1418 | } else { 1419 | if (isIterator(object)) { 1420 | return new ArrayList(new IteratorIterable(>object)); 1421 | } 1422 | } 1423 | return new ArrayList([object]); 1424 | } 1425 | 1426 | export class IteratorIterable extends AbstractIterator implements Iterable { 1427 | private iter: Iterator; 1428 | private iterResult: IteratorYieldResult | IteratorReturnResult; 1429 | private index: number = -1; // the lastIndex had been read 1430 | private firstReadByHasNextMethod: boolean = false; 1431 | 1432 | constructor(iterator: Iterator) { 1433 | super(); 1434 | Preconditions.checkNonNull(iterator); 1435 | this.iter = iterator; 1436 | this.iterResult = >Objects.unknownNull(); 1437 | } 1438 | 1439 | hasNext(): boolean { 1440 | // read unstart 1441 | if (this.iterResult == null && this.index == -1) { 1442 | try { 1443 | this.firstReadByHasNextMethod = true; 1444 | // read first 1445 | this.iterResult = this.iter.next(); 1446 | } catch (e) { 1447 | return false; 1448 | } 1449 | } 1450 | // had read some values 1451 | if (this.index >= 0) { 1452 | if (this.iterResult != null) { 1453 | return Booleans.asBoolean(this.iterResult.done); 1454 | } else { 1455 | return false; 1456 | } 1457 | } 1458 | return false; 1459 | } 1460 | 1461 | next(...args): IteratorYieldResult | IteratorReturnResult { 1462 | if (this.firstReadByHasNextMethod && this.index == 0 && this.iterResult != null) { 1463 | return this.iterResult; 1464 | } 1465 | this.index++; 1466 | this.iterResult = this.iter.next(); 1467 | return this.iterResult; 1468 | } 1469 | 1470 | [Symbol.iterator](): Iterator { 1471 | return this; 1472 | } 1473 | } 1474 | 1475 | export function hashCode(iterable: Iterable): number { 1476 | let hashCode: number = 0; 1477 | for (let element of iterable) { 1478 | hashCode += Objects.hashCode(element); 1479 | } 1480 | return hashCode; 1481 | } 1482 | 1483 | export class CompositeIterator extends AbstractIterator { 1484 | private readonly iterators: List> = emptyArrayList(); 1485 | private currentIteratorIndex = -1; 1486 | 1487 | constructor(iterators?: List>) { 1488 | super(); 1489 | if (iterators != null) { 1490 | this.iterators.addAll(iterators); 1491 | } 1492 | } 1493 | 1494 | addIterator(iterator: Iterator): void { 1495 | if (this.currentIteratorIndex < 0) { 1496 | this.iterators.add(iterator); 1497 | } 1498 | } 1499 | 1500 | next(...args: [] | [undefined]): IteratorResult { 1501 | if (this.currentIteratorIndex >= this.iterators.size()) { 1502 | return { 1503 | done: true, 1504 | value: Objects.unknownNull() 1505 | }; 1506 | } 1507 | if (this.currentIteratorIndex < 0) { 1508 | this.currentIteratorIndex = 0; 1509 | } 1510 | let currentIterator: Iterator = this.iterators.get(this.currentIteratorIndex); 1511 | let result: IteratorResult = currentIterator.next(); 1512 | if (!result.done) { 1513 | return result; 1514 | } else { 1515 | this.currentIteratorIndex++; 1516 | return this.next(...args); 1517 | } 1518 | } 1519 | 1520 | 1521 | } 1522 | -------------------------------------------------------------------------------- /src/main/Numbers.ts: -------------------------------------------------------------------------------- 1 | import * as Types from "./Types"; 2 | 3 | export function isFloat(n: number | string): boolean { 4 | let n1: Number = Number(n); 5 | if (!Types.isFunction(Number["isFloat"])) { 6 | Number["isFloat"] = (n2) => { 7 | if (!isNumber(n2)) { 8 | return false; 9 | } 10 | return n2.toString().indexOf(".") != -1; 11 | }; 12 | } 13 | return Number["isFloat"].call(Number, n1); 14 | } 15 | 16 | export function isInteger(n: number | string | any): boolean { 17 | let n1: Number = Number(n); 18 | if (!Types.isFunction(Number["isInteger"])) { 19 | Number["isInteger"] = (n2) => { 20 | if (!isNumber(n2)) { 21 | return false; 22 | } 23 | return n2.toString().indexOf(".") == -1; 24 | }; 25 | } 26 | return Number["isInteger"].call(Number, n1); 27 | } 28 | 29 | export function isNumber(obj: any): boolean { 30 | return !Number.isNaN(Number(obj)); 31 | } 32 | 33 | export function parseInt(str: string | String | number | Number, radix?: number): number { 34 | if (radix == null || radix < 2 || radix > 36) { 35 | radix = 10; 36 | } 37 | return Number.parseInt(str.toString(), radix); 38 | } 39 | 40 | export function hashCode(n: number) { 41 | return parseInt(n) 42 | } -------------------------------------------------------------------------------- /src/main/Objects.ts: -------------------------------------------------------------------------------- 1 | import * as HashCodes from "./HashCodes"; 2 | import * as Emptys from "./Emptys"; 3 | import * as Types from "./Types"; 4 | import * as Iterables from "./Iterables"; 5 | import * as Dates from "./Dates"; 6 | import {LinkedHashMap, ObjectPropertiesIterator} from "./Iterables"; 7 | import * as Collects from "./Collects"; 8 | import {type} from "os"; 9 | 10 | interface ObjectPropertyDescriptor { 11 | configurable?: boolean; 12 | enumerable?: boolean; 13 | value?: any; 14 | writable?: boolean; 15 | 16 | get?(): any; 17 | 18 | set?(v: any): void; 19 | } 20 | 21 | 22 | class SimpleObjectPropertyDescriptor implements ObjectPropertyDescriptor { 23 | configurable: boolean = true; 24 | enumerable: boolean = false; 25 | value: any; 26 | writable: boolean = true; 27 | } 28 | 29 | /** 30 | * @override Object.getPrototypeOf 31 | * @param obj 32 | */ 33 | export function getPrototypeOf(obj: any): any { 34 | if (obj == null) { 35 | return null; 36 | } 37 | if (!Types.isFunction(Object["getPrototypeOf"])) { 38 | // custom getPrototypeOf for Object 39 | Object["getPrototypeOf"] = getPrototypeOf; 40 | } else { 41 | // call ES API 42 | return Object.getPrototypeOf(obj); 43 | } 44 | return obj.prototype; 45 | } 46 | 47 | 48 | /** 49 | * @Override override Object.keys(obj) 50 | * @param obj 51 | */ 52 | export function keys(obj: object): Array { 53 | if (obj == null) { 54 | return []; 55 | } 56 | if (!Types.isFunction(Object["keys"])) { 57 | Object["keys"] = keys; 58 | } else { 59 | return Object["keys"](obj); 60 | } 61 | 62 | let ks: Array = []; 63 | for (let property in obj) { 64 | if (hasOwnProperty(obj, property)) { 65 | ks.push(property); 66 | } 67 | } 68 | return ks; 69 | } 70 | 71 | export function allEnumerableKeys(obj: object): Array { 72 | if (obj == null) { 73 | return []; 74 | } 75 | let ks: Array = []; 76 | for (let property in obj) { 77 | ks.push(property); 78 | } 79 | return ks; 80 | } 81 | 82 | /** 83 | * @Override override Object.getOwnPropertyDescriptor(obj:object, property:string) 84 | * @param obj 85 | * @param property 86 | */ 87 | export function getOwnPropertyDescriptor(obj: object, property: string | number | symbol): object | undefined | null | ObjectPropertyDescriptor { 88 | if (!Types.isFunction(Object["getOwnPropertyDescriptor"])) { 89 | Object["getOwnPropertyDescriptor"] = (function () { 90 | return function (o: object, prop: string | number | symbol) { 91 | let oPrototype = getPrototypeOf(o); 92 | if (hasOwnProperty(oPrototype, prop)) { 93 | return new SimpleObjectPropertyDescriptor(); 94 | } else { 95 | return undefined; 96 | } 97 | } 98 | })(); 99 | } 100 | return Object.getOwnPropertyDescriptor(obj, property); 101 | } 102 | 103 | export function getPropertyDescriptor(obj: object, property: string | number | symbol): object | null | ObjectPropertyDescriptor { 104 | let desc = getOwnPropertyDescriptor(obj, property); 105 | if (desc == null) { 106 | desc = getPropertyDescriptor(getPrototypeOf(obj), property); 107 | } 108 | return desc; 109 | } 110 | 111 | export function hasProperty(obj: object, property: string | number | symbol): boolean { 112 | if (hasOwnProperty(obj, property)) { 113 | return true; 114 | } 115 | return hasProperty(getPrototypeOf(obj), property); 116 | } 117 | 118 | /** 119 | * @Override Object.prototype.hasOwnProperty(property) 120 | */ 121 | export function hasOwnProperty(obj: object, property: string | number | symbol): boolean { 122 | if (!Types.isFunction(Object.prototype["hasOwnProperty"])) { 123 | Object.prototype["hasOwnProperty"] = function (prop: string): boolean { 124 | if (this.prototype != this.prototype.prototype) { 125 | let v = this.prototype[prop] != null; 126 | return v != null && this.prototype.prototype[prop] != v; 127 | } else { 128 | return this.prototype[prop] != null; 129 | } 130 | }; 131 | } 132 | return obj.hasOwnProperty(property); 133 | } 134 | 135 | /** 136 | * @Override Object.prototype.propertyIsEnumerable() 137 | * @param obj 138 | * @param property 139 | */ 140 | export function propertyIsEnumerable(obj: object, property: string | number | symbol): boolean { 141 | if (obj == null || property == null) { 142 | return false; 143 | } 144 | if (!Types.isFunction(Object.prototype["propertyIsEnumerable"])) { 145 | Object.prototype["propertyIsEnumerable"] = function (prop: string | number | symbol) { 146 | for (let key in this) { 147 | if (key == prop) { 148 | return true; 149 | } 150 | } 151 | return false; 152 | } 153 | } 154 | return obj.propertyIsEnumerable(property); 155 | } 156 | 157 | export function hasOwnEnumerableProperty(obj: any, property: string | number | symbol): boolean { 158 | if (obj == null || property == null) { 159 | return false; 160 | } 161 | return hasOwnProperty(obj, property) && propertyIsEnumerable(obj, property); 162 | } 163 | 164 | /** 165 | * @Override Object.defineProperty(obj, prop, descriptor) 166 | * @param obj 167 | * @param property 168 | * @param descriptor 169 | */ 170 | export function defineProperty(obj: any, property: string | number | symbol, descriptor: object | ObjectPropertyDescriptor | null | undefined) { 171 | if (obj == null || property == null || descriptor == null) { 172 | return; 173 | } 174 | if (!Types.isFunction(Object["defineProperty"])) { 175 | Object["defineProperty"] = function (o: object, prop: string | number | symbol, desc: object | ObjectPropertyDescriptor) { 176 | o[prop] = desc["value"]; 177 | } 178 | } 179 | Object.defineProperty(obj, property, descriptor); 180 | } 181 | 182 | export function definePrototypeProperty(obj: object, property: string | number | symbol, desc: ObjectPropertyDescriptor): void { 183 | defineProperty(getPrototypeOf(obj), property, desc); 184 | } 185 | 186 | 187 | export function isNull(obj: any): boolean { 188 | return Emptys.isNull(obj); 189 | } 190 | 191 | export function isNotNull(obj: any) { 192 | return Emptys.isNotNull(obj); 193 | } 194 | 195 | export function isEmpty(obj: any): boolean { 196 | return Emptys.isEmpty(obj); 197 | } 198 | 199 | export function isNotEmpty(obj: any) { 200 | return Emptys.isNotEmpty(obj); 201 | } 202 | 203 | export function unknownNull(): unknown { 204 | return null; 205 | } 206 | 207 | export function hashCode(object: any): number { 208 | return HashCodes.hashCode(object); 209 | } 210 | 211 | export function getLength(obj: any): number { 212 | return Emptys.getLength(obj); 213 | } 214 | 215 | export function objectToMap(obj: object) { 216 | let map: LinkedHashMap = new LinkedHashMap(); 217 | if (isEmpty(obj)) { 218 | return map; 219 | } 220 | for (let entry of new ObjectPropertiesIterator(obj)) { 221 | map.put(entry.key, entry.value); 222 | } 223 | return map; 224 | } 225 | 226 | export function equals(obj1: any, obj2: any, deep?: boolean) { 227 | if (obj1 === obj2) { 228 | return true; 229 | } 230 | 231 | if (!deep) { 232 | return false; 233 | } 234 | 235 | if (Types.isDate(obj1)) { 236 | return Dates.equals(obj1, obj2); 237 | } 238 | 239 | let obj1IsIterable = Iterables.isIterable(obj1); 240 | let obj2IsIterable = Iterables.isIterable(obj2); 241 | if (!obj1IsIterable && obj2IsIterable) { 242 | return false; 243 | } 244 | if (!obj1IsIterable && !obj2IsIterable) { 245 | obj1 = objectToMap(obj1); 246 | obj2 = objectToMap(obj2); 247 | } 248 | if (obj1IsIterable && !obj2IsIterable) { 249 | obj2 = objectToMap(obj2); 250 | } 251 | return Collects.containsAll(obj1, obj2, deep) && Collects.containsAll(obj2, obj1, deep); 252 | } 253 | 254 | export function isObjectKeyType(type:any){ 255 | return type ==String; 256 | } 257 | 258 | export function isMapKeyType(type:any) { 259 | return type==Symbol || type == String || type == Number; 260 | } -------------------------------------------------------------------------------- /src/main/Pipeline.ts: -------------------------------------------------------------------------------- 1 | import {Collection, HashSet, LikeJavaMap, LikeJavaSet, List} from "./Iterables"; 2 | import * as Collects from "./Collects"; 3 | import {Consumer, Consumer2, Func, Func2, Predicate, Predicate2, Supplier0} from "./Functions"; 4 | import * as Objects from "./Objects"; 5 | import {Comparator} from "./Comparators"; 6 | import * as Collectors from "./Collectors"; 7 | import {Collector} from "./Collectors"; 8 | 9 | export class Pipeline { 10 | private readonly collection: Collection; 11 | 12 | new(list?: Iterable | Iterator | any) { 13 | return new Pipeline(list); 14 | } 15 | 16 | constructor(list?: Iterable | Iterator | any) { 17 | if (list == null) { 18 | this.collection = Collects.emptyArrayList(); 19 | } 20 | this.collection = Collects.asList(list); 21 | } 22 | 23 | forEach(consumer: Consumer | Consumer2 | Function, consumePredicate?: Predicate | Predicate2 | Function, breakPredicate?: Predicate | Predicate2 | Function): void { 24 | Collects.forEach(this.collection, consumer, consumePredicate, breakPredicate); 25 | } 26 | 27 | map(mapper: Func | Func2 | Function): Pipeline { 28 | return new Pipeline(Collects.map(this.collection, mapper)); 29 | } 30 | 31 | filter(predicate: Predicate | Predicate2 | Function, breakPredicate?: Predicate | Predicate2 | Function): Pipeline { 32 | return new Pipeline(Collects.filter(this.collection, predicate, breakPredicate)); 33 | } 34 | 35 | findN(predicate: Predicate | Predicate2 | Function, count: number): Pipeline { 36 | return new Pipeline(Collects.findN(this.collection, predicate, count)); 37 | } 38 | 39 | findFirst(predicate?: Predicate | Predicate2 | Function): null | E { 40 | if (predicate == null) { 41 | predicate = >Objects.unknownNull(); 42 | } 43 | return Collects.findFirst(this.collection, predicate); 44 | } 45 | 46 | asSet(): LikeJavaSet { 47 | return >this.collect(Collectors.toHashSet()); 48 | } 49 | 50 | asList(): List { 51 | return >this.collect(Collectors.toArrayList()); 52 | } 53 | 54 | toArray(array?: Array): Array { 55 | return Collects.toArray(this.collection, array); 56 | } 57 | 58 | cleanNulls() { 59 | return new Pipeline(Collects.cleanNulls(this.collection)); 60 | } 61 | 62 | flatMap(mapper?: Func | Func2 | Function) { 63 | return new Pipeline(Collects.flatMap(this.collection, mapper)); 64 | } 65 | 66 | anyMatch(predicate: Predicate | Predicate2 | Function): boolean { 67 | return Collects.anyMatch(this.collection, predicate); 68 | } 69 | 70 | allMatch(predicate: Predicate | Predicate2 | Function): boolean { 71 | return Collects.allMatch(this.collection, predicate); 72 | } 73 | 74 | noneMatch(predicate: Predicate | Predicate2 | Function): boolean { 75 | return Collects.noneMatch(this.collection, predicate); 76 | } 77 | 78 | limit(limit: number): Pipeline { 79 | return new Pipeline(Collects.limit(this.collection, Math.max(0, limit))); 80 | } 81 | 82 | skip(skip: number): Pipeline { 83 | return new Pipeline(Collects.skip(this.collection, Math.max(0, skip))); 84 | } 85 | 86 | distinct(comparator?: Comparator): Pipeline { 87 | return new Pipeline(Collects.distinct(this.collection)); 88 | } 89 | 90 | reverse(newOne?: boolean): Pipeline { 91 | return new Pipeline(Collects.reverse(this.collection)); 92 | } 93 | 94 | count(predicate?: Function | Predicate | Predicate2): number { 95 | return Collects.count(this.collection, predicate); 96 | } 97 | 98 | isEmpty(): boolean { 99 | return this.count() == 0; 100 | } 101 | 102 | addAll(appendment: Iterable): Pipeline { 103 | Collects.addAll(this.collection, appendment); 104 | return this; 105 | } 106 | 107 | contains(element: any, deep?: boolean): boolean { 108 | return Collects.contains(this.collection, element, deep); 109 | } 110 | 111 | containsAll(iterable: Iterable, deep?: boolean): boolean { 112 | return Collects.contains(this.collection, iterable, deep); 113 | } 114 | 115 | containsAny(iterable: Iterable, deep?: boolean): boolean { 116 | return Collects.contains(this.collection, iterable, deep); 117 | } 118 | 119 | containsNone(iterable: Iterable, deep?: boolean): boolean { 120 | return Collects.contains(this.collection, iterable, deep); 121 | } 122 | 123 | collect(collector: Collector, any>): Iterable { 124 | return Collectors.collect(this.collection, collector); 125 | } 126 | 127 | groupBy(classifier: Func | Func2 | Function, mapFactory: Supplier0>>): LikeJavaMap> { 128 | return Collects.groupBy(classifier, mapFactory); 129 | } 130 | 131 | partitionBy(classifier: Func | Func2 | Function): List> { 132 | return Collects.partitionBy(this.collection, classifier); 133 | } 134 | 135 | intersection(iterable2: Iterable|null|undefined): Pipeline { 136 | return of(Collects.intersection(this.collection, iterable2)); 137 | } 138 | 139 | union(iterable2: Iterable): Pipeline { 140 | return of(Collects.union(this.collection, iterable2)); 141 | } 142 | } 143 | 144 | 145 | export function of(list?: Iterable | Iterator | any) { 146 | return new Pipeline(list); 147 | } 148 | 149 | Pipeline["of"] = of; 150 | -------------------------------------------------------------------------------- /src/main/Preconditions.ts: -------------------------------------------------------------------------------- 1 | import * as Emptys from './Emptys'; 2 | import {RuntimeException} from "./Exceptions"; 3 | import {Predicate, Predicate2} from "./Functions"; 4 | import * as Types from "./Types"; 5 | 6 | export function checkNonNull(obj: any, message?: string | String | Function): any { 7 | if (Emptys.isNull(obj)) { 8 | if (message == null) { 9 | message = "is null"; 10 | } 11 | throw new RuntimeException(message); 12 | } 13 | return obj; 14 | } 15 | 16 | export function checkNull(obj: any, message?: string | String | Function) { 17 | if (Emptys.isNotNull(obj)) { 18 | if (message == null) { 19 | message = "is not null"; 20 | } 21 | throw new RuntimeException(message); 22 | } 23 | return obj; 24 | } 25 | 26 | export function checkTrue(expression: boolean | Boolean | Predicate | Predicate2, message?: string | String | Function): boolean { 27 | if (expression instanceof Function) { 28 | expression = (expression)(); 29 | } 30 | 31 | if (!expression) { 32 | if (message == null) { 33 | message = "is not true expression"; 34 | } 35 | throw new RuntimeException(message); 36 | } 37 | return true; 38 | } 39 | 40 | export function checkIndex(expression: boolean | Boolean | Predicate | Predicate2, message?: string | String | Function): boolean { 41 | if (expression instanceof Function) { 42 | expression = (expression)(); 43 | } 44 | 45 | if (!expression) { 46 | if (message == null) { 47 | message = "Index outbound"; 48 | } 49 | throw new RuntimeException(message); 50 | } 51 | return true; 52 | } 53 | 54 | export function test(predicate: Predicate | Predicate2, args: any): boolean { 55 | if (Types.isArray(args)) { 56 | const argsLength = Emptys.getLength(args); 57 | if (argsLength == 2) { 58 | return (>predicate).test(args[0], args[1]); 59 | } else { 60 | return (>predicate).test(args[0]); 61 | } 62 | } 63 | return (>predicate).test(args); 64 | } -------------------------------------------------------------------------------- /src/main/Strings.ts: -------------------------------------------------------------------------------- 1 | import {isEmpty} from "./Objects"; 2 | 3 | export function hashCode(str: string | String): number { 4 | if (isEmpty(str)) { 5 | return 0; 6 | } 7 | 8 | let hash = 0; 9 | for (let i: number = 0; i < str.length; i++) { 10 | hash = 31 * hash + str.charCodeAt(i); 11 | } 12 | return hash; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/Types.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AbstractCollection, 3 | AbstractList, 4 | AbstractMap, 5 | AbstractSet, 6 | ArrayList, 7 | HashMap, 8 | HashSet, 9 | LinkedList 10 | } from "./Iterables"; 11 | 12 | import * as Objects from "./Objects"; 13 | 14 | export function getType(object: any): any { 15 | if (Objects.isNull(object)) { 16 | return undefined; 17 | } 18 | let typeString = typeof object; 19 | var type: any = undefined; 20 | switch (typeString) { 21 | case "undefined": 22 | type = undefined; 23 | break; 24 | case "boolean": 25 | type = Boolean; 26 | break; 27 | case "string": 28 | type = String; 29 | break; 30 | case "function": 31 | type = Function; 32 | break; 33 | case "bigint": 34 | case "number": 35 | type = Number; 36 | break; 37 | case "symbol": 38 | type = Symbol; 39 | case "object": 40 | type = Object; 41 | break; 42 | default: 43 | type = Object; 44 | } 45 | if (type != undefined && type != Object) { 46 | return type; 47 | } 48 | 49 | if (type == Symbol) { 50 | return Symbol; 51 | } 52 | 53 | if (object instanceof Date) { 54 | return Date; 55 | } 56 | 57 | if (Array.isArray(object)) { 58 | return Array; 59 | } 60 | 61 | if (object instanceof Map) { 62 | return Map; 63 | } 64 | 65 | if (object instanceof WeakMap) { 66 | return WeakMap; 67 | } 68 | 69 | if (object instanceof AbstractMap) { 70 | if (object instanceof HashMap) { 71 | return HashMap; 72 | } 73 | return AbstractMap; 74 | } 75 | 76 | if (object instanceof Set) { 77 | return Set; 78 | } 79 | if (object instanceof WeakSet) { 80 | return WeakSet; 81 | } 82 | 83 | if (object instanceof AbstractSet) { 84 | if (object instanceof HashSet) { 85 | return HashSet; 86 | } 87 | return AbstractSet; 88 | } 89 | 90 | if (object instanceof AbstractList) { 91 | if (object instanceof ArrayList) { 92 | return ArrayList; 93 | } 94 | if (object instanceof LinkedList) { 95 | return LinkedList; 96 | } 97 | return AbstractList; 98 | } 99 | 100 | if (object instanceof AbstractCollection) { 101 | return AbstractCollection; 102 | } 103 | 104 | if (object instanceof Error) { 105 | return Error; 106 | } 107 | return type; 108 | } 109 | 110 | export function isString(object: any): boolean { 111 | return getType(object) == String; 112 | } 113 | 114 | export function isNumber(object: any): boolean { 115 | return getType(object) == Number; 116 | } 117 | 118 | export function isBoolean(object: any): boolean { 119 | return getType(object) == Boolean; 120 | } 121 | 122 | export function isDate(object: any): boolean { 123 | return getType(object) == Date; 124 | } 125 | 126 | export function isFunction(object: any): boolean { 127 | return getType(object) == Function; 128 | } 129 | 130 | export function isArray(object: any): boolean { 131 | return getType(object) == Array; 132 | } 133 | 134 | 135 | export function isWeakSet(object: any): boolean { 136 | return getType(object) == WeakSet; 137 | } 138 | 139 | export function isJsMap(object: any): boolean { 140 | let type: any = getType(object); 141 | return type == Map || type == WeakMap; 142 | } 143 | 144 | export function isMap(object: any) { 145 | return isJsMap(object) || isJavaMap(object); 146 | } 147 | 148 | export function isWeakMap(object: any): boolean { 149 | return getType(object) == WeakMap; 150 | } 151 | 152 | export function isError(object: any): boolean { 153 | return getType(object) == Error; 154 | } 155 | 156 | export function isCollection(object: any): boolean { 157 | return isArray(object) || isJsSet(object) || isJavaCollection(object); 158 | } 159 | 160 | export function isJavaCollection(object: any) { 161 | return object instanceof AbstractCollection; 162 | } 163 | 164 | export function isJavaMap(object: any) { 165 | return object instanceof AbstractMap; 166 | } 167 | 168 | export function isJavaSet(object: any) { 169 | return object instanceof AbstractSet; 170 | } 171 | 172 | export function isJsSet(object: any): boolean { 173 | let type: any = getType(object); 174 | return type == Set; 175 | } 176 | 177 | export function isSet(object: any) { 178 | return isJsSet(object) || isJavaSet(object); 179 | } 180 | 181 | export function isSimpleObject(object: any): boolean { 182 | return !isFunction(object) 183 | && !isNumber(object) 184 | && !isString(object) 185 | && !isBoolean(object) 186 | && !isDate(object) 187 | && !isMap(object) 188 | && !isCollection(object) 189 | && !isError(object) 190 | && !isSymbol(object) 191 | ; 192 | } 193 | 194 | export function isSymbol(object: any): boolean { 195 | return getType(object) == Symbol; 196 | } -------------------------------------------------------------------------------- /src/main/index.ts: -------------------------------------------------------------------------------- 1 | import * as HashCodes from "./HashCodes"; 2 | import * as Objects from "./Objects"; 3 | import * as Strings from "./Strings"; 4 | import * as Tyeps from "./Types"; 5 | import * as Emptys from "./Emptys"; 6 | import * as Exceptions from "./Exceptions"; 7 | import * as Numbers from "./Numbers"; 8 | import * as Dates from "./Dates"; 9 | import * as Booleans from "./Booleans"; 10 | import * as logger from "./logger"; 11 | import * as Functions from "./Functions"; 12 | import * as Preconditions from "./Preconditions"; 13 | import * as Iterables from "./Iterables"; 14 | import * as Collects from "./Collects"; 15 | import * as Pipeline from "./Pipeline"; 16 | 17 | export { 18 | HashCodes, 19 | Objects, 20 | Strings, 21 | Tyeps, 22 | Emptys, 23 | Exceptions, 24 | Numbers, 25 | Dates, 26 | Booleans, 27 | logger, 28 | Functions, 29 | Preconditions, 30 | Iterables, 31 | Collects, 32 | Pipeline 33 | } 34 | -------------------------------------------------------------------------------- /src/main/lodash.ts: -------------------------------------------------------------------------------- 1 | import * as Objects from "./Objects"; 2 | import * as Numbers from "./Numbers"; 3 | import * as Collects from "./Collects"; 4 | import {ArrayList, HashMap, List, MapEntry, ObjectPropertiesIterateType, ObjectPropertiesIterator} from "./Iterables"; 5 | import * as Pipeline from "./Pipeline"; 6 | import * as Types from "./Types"; 7 | import * as Preconditions from "./Preconditions"; 8 | import * as Comparators from "./Comparators"; 9 | import {Comparator, EqualsComparator, FunctionComparator, IsComparator, ObjectComparator} from "./Comparators"; 10 | import * as Functions from "./Functions"; 11 | import {Func, Func2, Predicate, Predicate2, truePredicate} from "./Functions"; 12 | import * as Algorithms from "./Algorithms"; 13 | import {SearchResult} from "./Algorithms"; 14 | import {IllegalArgumentException} from "./Exceptions"; 15 | 16 | 17 | export function chunk(array: Array, size?: number): Array> { 18 | let size0: number = size == null ? 1 : Numbers.parseInt(size); 19 | let result: Array> = []; 20 | let tmp: Array; 21 | Collects.forEach(array, { 22 | accept(index: number, element: any) { 23 | let newArray: boolean = index % size0 == 0; 24 | if (newArray) { 25 | tmp = []; 26 | result.push(tmp); 27 | } 28 | tmp.push(element); 29 | } 30 | }); 31 | return result; 32 | } 33 | 34 | export function compact(array: Array): Array { 35 | return Pipeline.of(array).filter({ 36 | test(element: any): boolean { 37 | return element ? true : false; 38 | } 39 | }).toArray(); 40 | } 41 | 42 | export function concat(array: Array, ...a2): Array { 43 | return Collects.concat(array, a2); 44 | } 45 | 46 | export function difference(array: Array, a2: Array) { 47 | return Pipeline.of(array).filter({ 48 | test(element: any) { 49 | return Collects.contains(a2, element, false); 50 | } 51 | }).toArray([]); 52 | } 53 | 54 | export function differenceBy(array: Array, a2: Array, mapper: string | object | Array | Function): Array { 55 | if (Objects.isNull(mapper)) { 56 | return difference(array, a2); 57 | } 58 | if (Objects.isEmpty(a2)) { 59 | return Collects.toArray(array, []); 60 | } 61 | let m: Function = _buildArrayMapper(mapper); 62 | let list2: Iterable | undefined = Collects.map(a2, m); 63 | return Pipeline.of(array).filter({ 64 | test(element: any, index: number) { 65 | return Collects.contains(list2, Functions.mapping(m, element, index), false); 66 | } 67 | }).toArray(); 68 | } 69 | 70 | export function differenceWith(array: Array, values: Array, comparator: Comparator | Function | Func2) { 71 | let predicate: Predicate2 = Functions.wrappedPredicate2(comparator); 72 | return Pipeline.of(array).filter({ 73 | test(element: any) { 74 | return Collects.anyMatch(values, predicate); 75 | } 76 | }).toArray([]); 77 | } 78 | 79 | 80 | export function drop(array: Array, n: number): Array { 81 | n = (n == null || n < 0) ? 1 : 0; 82 | Preconditions.checkTrue(Types.isArray(array)); 83 | for (let i = 0; i < n; i++) { 84 | if (array.length > 0) { 85 | array.shift(); 86 | } 87 | } 88 | return array; 89 | } 90 | 91 | export function dropRight(array: Array, n: number): Array { 92 | Preconditions.checkTrue(Types.isArray(array)); 93 | n = (n == null || n < 0) ? 1 : 0; 94 | n = n > array.length ? array.length : n; 95 | array.splice(array.length - n, n); 96 | return array; 97 | } 98 | 99 | 100 | function _buildArrayPredicate(predicate: string | object | Array | Function): Function | Predicate2 | Predicate { 101 | Preconditions.checkNonNull(predicate); 102 | let p: Function | Predicate2 | Predicate; 103 | 104 | // [0] property 105 | // [1] value 106 | if (Types.isArray(predicate)) { 107 | Preconditions.checkTrue((>predicate).length >= 2); 108 | Preconditions.checkTrue(Types.isString(predicate[0])); 109 | let property = predicate[0]; 110 | p = function (element) { 111 | return element[property] == predicate[1]; 112 | }; 113 | } else 114 | // .property 115 | if (Types.isString(predicate)) { 116 | let property = predicate; 117 | p = function (element) { 118 | return element[property]; 119 | }; 120 | } else if (Functions.isPredicate(predicate)) { 121 | p = >predicate; 122 | } else if (Types.isSimpleObject(predicate)) { 123 | p = function (element) { 124 | let match = true; 125 | for (let entry of new ObjectPropertiesIterator(predicate, ObjectPropertiesIterateType.KEY_VALUE)) { 126 | if (element[entry.key] !== entry.value) { 127 | match = false; 128 | break; 129 | } 130 | } 131 | return match; 132 | }; 133 | } else { 134 | p = Functions.truePredicate(); 135 | } 136 | return p; 137 | } 138 | 139 | 140 | function _buildArrayMapper(mapper: string | object | Array | Function): Function | Func | Func2 { 141 | Preconditions.checkNonNull(mapper); 142 | let m: Function | Func | Func2; 143 | 144 | // [0] property 145 | // [1] value 146 | if (Types.isArray(mapper)) { 147 | let properties: Array = >mapper; 148 | Preconditions.checkTrue(properties.length >= 1); 149 | m = function (element) { 150 | let obj = {}; 151 | for (let property of properties) { 152 | obj[property] = element[property]; 153 | } 154 | return obj; 155 | } 156 | } else 157 | // .property 158 | if (Types.isString(mapper)) { 159 | let property = mapper; 160 | m = function (element) { 161 | return element[property]; 162 | }; 163 | } else if (Functions.isPredicate(mapper)) { 164 | m = mapper; 165 | } else if (Types.isSimpleObject(mapper)) { 166 | m = Functions.noopFunction(); 167 | } else { 168 | m = Functions.noopFunction(); 169 | } 170 | return m; 171 | } 172 | 173 | 174 | function _dropCountWhile(array: Array, predicate: string | object | Array | Function): number { 175 | Preconditions.checkTrue(Types.isArray(array)); 176 | predicate = _buildArrayPredicate(predicate); 177 | 178 | let count = 0; 179 | let breakPredicate = function (element, index) { 180 | let b = !Functions.callPredicate(predicate, element, index, array); 181 | if (!b) { 182 | count++; 183 | } 184 | return b; 185 | }; 186 | Collects.forEach(array, Functions.noopConsumer(), truePredicate(), breakPredicate); 187 | return count; 188 | } 189 | 190 | export function dropWhile(array: Array, predicate: string | object | Array | Function) { 191 | let count: number = _dropCountWhile(array, predicate); 192 | array.splice(0, count); 193 | return array; 194 | } 195 | 196 | export function dropRightWhile(array: Array, predicate: string | object | Array | Function) { 197 | array = array.reverse(); 198 | array = dropWhile(array, predicate); 199 | return array.reverse(); 200 | } 201 | 202 | export function fill(array: Array, value: any, fromIndex: number, toIndex: number): Array { 203 | Preconditions.checkTrue(Types.isArray(array)); 204 | toIndex = toIndex == null || toIndex > array.length ? array.length : toIndex; 205 | fromIndex = fromIndex == null || fromIndex < 0 ? 0 : fromIndex; 206 | fromIndex = fromIndex > toIndex ? toIndex : fromIndex; 207 | while (fromIndex < toIndex) { 208 | array[fromIndex] = value; 209 | } 210 | return array; 211 | } 212 | 213 | 214 | export function findIndex(array: Array, predicate: string | object | Array | Function): number { 215 | predicate = _buildArrayPredicate(predicate); 216 | let index = -1; 217 | Collects.forEach(array, function (element, i) { 218 | index = i; 219 | }, predicate, { 220 | test(i: any) { 221 | return index !== -1; 222 | } 223 | }); 224 | return index; 225 | } 226 | 227 | export function findLastIndex(array: Array, predicate?: string | object | Array | Function): number { 228 | predicate = _buildArrayPredicate(predicate ? predicate : truePredicate()); 229 | let index = -1; 230 | Pipeline.of(array).reverse().forEach(function (element, i) { 231 | index = i; 232 | }, predicate, { 233 | test(i: any) { 234 | return index !== -1; 235 | } 236 | }); 237 | if (index !== -1) { 238 | index = array.length - 1 - index; 239 | } 240 | return index; 241 | } 242 | 243 | export function first(array: Array): any { 244 | return nth(array, 0); 245 | } 246 | 247 | export function flatten(array: Array | any): Array { 248 | let newArray: Array = []; 249 | array = Collects.asList(array).toArray(); 250 | Collects.forEach(array, (element) => { 251 | Collects.addAll(newArray, Collects.asList(element)); 252 | }); 253 | return newArray; 254 | } 255 | 256 | export function flattenDeep(array: Array | any): Array { 257 | let newArray: Array = []; 258 | array = Collects.asList(array).toArray(); 259 | Collects.forEach(array, (element) => { 260 | Collects.addAll(newArray, flattenDeep(element)); 261 | }); 262 | return newArray; 263 | } 264 | 265 | export function flattenDepth(array: Array | any, depth?: number, currentDepth?: number) { 266 | depth = depth == null || !depth || depth < 1 ? 1 : depth; 267 | let current = (currentDepth == null || !currentDepth || currentDepth < -1) ? 0 : currentDepth; 268 | array = Collects.asList(array).toArray(); 269 | if (current < depth) { 270 | let newArray: Array = []; 271 | Collects.forEach(array, (element) => { 272 | current++; 273 | Collects.addAll(newArray, flattenDepth(element, depth, current)); 274 | }); 275 | return newArray; 276 | } 277 | return array; 278 | } 279 | 280 | export function fromPairs(pairs: Array>): object { 281 | let obj = {}; 282 | Collects.forEach(pairs, { 283 | accept(pair: Array) { 284 | obj[pair[0]] = pair[1]; 285 | } 286 | }, (pair: Array) => { 287 | return Types.isArray(pair) && pair.length >= 2 && Objects.isObjectKeyType(Types.getType(pair[0])); 288 | }); 289 | return obj; 290 | } 291 | 292 | export function head(array: Array): any { 293 | return first(array); 294 | } 295 | 296 | export function indexOf(array: Array, value: any, fromIndex?: number): number { 297 | fromIndex = (fromIndex == null || fromIndex < 0) ? 0 : Numbers.parseInt(fromIndex); 298 | if (fromIndex >= array.length) { 299 | return -1; 300 | } 301 | let index: number = Collects.newArrayList(array.slice(fromIndex)).indexOf(value); 302 | return index == -1 ? -1 : (fromIndex + index); 303 | } 304 | 305 | export function initial(array: Array) { 306 | if (array.length >= 1) { 307 | array.splice(array.length - 1, 1); 308 | } 309 | return array; 310 | } 311 | 312 | export function intersection(...arrays: Array) { 313 | if (arrays.length < 1) { 314 | return []; 315 | } 316 | let pipeline = Pipeline.of(arrays.shift()); 317 | while (arrays.length > 0 && !pipeline.isEmpty()) { 318 | let arr2: Array = arrays.shift(); 319 | pipeline = pipeline.intersection(arr2); 320 | } 321 | return pipeline.toArray(); 322 | } 323 | 324 | export function intersectionBy(arrays: Array>, mapper: string | object | Array | Function) { 325 | if (arrays.length < 1) { 326 | return []; 327 | } 328 | let m: Function = _buildArrayMapper(mapper); 329 | 330 | let pipeline = Pipeline.of(arrays.shift()); 331 | while (arrays.length > 0 && !pipeline.isEmpty()) { 332 | let array: Array = >arrays.shift(); 333 | if (array != null) { 334 | let arr2 = Collects.map(array, m); 335 | pipeline = pipeline.filter({ 336 | test(element: any) { 337 | return Collects.contains(arr2, Functions.mapping(m, element)); 338 | } 339 | }); 340 | } else { 341 | return []; 342 | } 343 | } 344 | return pipeline.toArray(); 345 | } 346 | 347 | 348 | export function intersectionWith(arrays: Array>, comparator: Comparator | Func2 | Function) { 349 | if (arrays.length < 1) { 350 | return []; 351 | } 352 | let _comparator: Comparator = Comparators.functionComparator(comparator); 353 | 354 | let pipeline = Pipeline.of(arrays.shift()); 355 | while (arrays.length > 0 && !pipeline.isEmpty()) { 356 | let array: Array = >arrays.shift(); 357 | if (array != null) { 358 | pipeline = pipeline.filter({ 359 | test(element: any) { 360 | return Collects.anyMatch(array, { 361 | test(element2: any) { 362 | return _comparator.compare(element, element2) == 0; 363 | } 364 | }) 365 | } 366 | }); 367 | } else { 368 | return []; 369 | } 370 | } 371 | return pipeline.toArray(); 372 | } 373 | 374 | export function join(array: Array, separator?: string): string { 375 | let str = ""; 376 | separator = separator == null || !Types.isString(separator) ? "," : separator; 377 | Collects.forEach(array, (element: any, index: number) => { 378 | str = str + (index == 0 ? "" : separator) + element.toString(); 379 | }, (element: any, index: number) => { 380 | return element != null; 381 | }); 382 | return str; 383 | } 384 | 385 | export function last(array: Array): any { 386 | return nth(array, array.length - 1); 387 | } 388 | 389 | export function lastIndexOf(array: Array, value: any, fromIndex?: number): number { 390 | fromIndex = (fromIndex == null || fromIndex >= array.length) ? (array.length - 1) : fromIndex; 391 | if (fromIndex < 0) { 392 | return -1; 393 | } 394 | return Collects.newArrayList(array.slice(0, fromIndex + 1)).lastIndexOf(value); 395 | } 396 | 397 | export function nth(array: Array, n: number): any { 398 | let list: List = Collects.asList(array); 399 | if (n < 0) { 400 | n = list.size() - 1 + n; 401 | } 402 | if (n >= list.size() || n < 0) { 403 | return null; 404 | } 405 | return list.get(n); 406 | } 407 | 408 | export function put(array: Array, ...values: any): Array { 409 | let list: List = Collects.asList(Collects.asIterable(values)); 410 | Collects.removeIf(array, (element: any) => { 411 | return list.contains(element); 412 | }); 413 | return array; 414 | } 415 | 416 | export function putAll(array: Array, values: Array): Array { 417 | return put(array, ...values); 418 | } 419 | 420 | export function putAllBy(array: Array, values: Array, mapper: string | object | Array | Function): Array { 421 | let m: Function = _buildArrayMapper(mapper); 422 | let list: List = >Collects.map(values, m); 423 | Collects.removeIf(array, (element: any, index: number) => { 424 | return list.contains(Functions.mapping(m, element, index)); 425 | }); 426 | return array; 427 | } 428 | 429 | export function putAllWith(array: Array, values: Array, comparator: Comparator | Func2 | Function): Array { 430 | let _comparator: Comparator = Comparators.functionComparator(comparator); 431 | Collects.removeIf(array, (element: any) => { 432 | Collects.anyMatch(values, (value: any) => { 433 | return _comparator.compare(element, value) == 0; 434 | }) 435 | }); 436 | return array; 437 | } 438 | 439 | export function putAt(array: Array, ...indexes: Array): Array { 440 | let removed: Array = []; 441 | let unremoved: Array = []; 442 | Collects.forEach(array, (element: any, index: number) => { 443 | if (Collects.contains(indexes, index)) { 444 | removed.push(element); 445 | } else { 446 | unremoved.push(element); 447 | } 448 | }); 449 | array.splice(0); 450 | array.push(...unremoved); 451 | return removed; 452 | } 453 | 454 | export function remove(array: Array, predicate: string | object | Array | Function): Array { 455 | let removed: Array = []; 456 | let _predicate = _buildArrayPredicate(predicate); 457 | for (let i = 0; i < array.length;) { 458 | let element = array[i]; 459 | if (Functions.test(_predicate, element, i)) { 460 | removed.push(element); 461 | array.slice(i, 1); 462 | } else { 463 | i++; 464 | } 465 | } 466 | return removed; 467 | } 468 | 469 | export function reverse(array: Array): Array { 470 | return >Collects.reverse(array, false); 471 | } 472 | 473 | export function slice(array: Array, start?: number, end?: number): Array { 474 | end = end == null || !Types.isNumber(end) || end < 0 || end >= array.length ? array.length : end; 475 | start = start == null || !Types.isNumber(start) || start < 0 ? 0 : start; 476 | if (start > end || start >= array.length) { 477 | return array; 478 | } 479 | return array.slice(start, end); 480 | } 481 | 482 | export function sortedIndex(array: Array, value: any): number { 483 | return Algorithms.binarySearch(Collects.newArrayList(array), value, new ObjectComparator(), true).index; 484 | } 485 | 486 | export function sortedIndexBy(array: Array, value: any, mapper: string | object | Array | Function): number { 487 | let m = _buildArrayMapper(mapper); 488 | let comparator = new ObjectComparator(); 489 | return Algorithms.binarySearch(Collects.newArrayList(array), value, new FunctionComparator((e1: any, e2: any) => { 490 | e1 = Functions.mapping(m, e1); 491 | e2 = Functions.mapping(m, e2); 492 | return comparator.compare(e1, e2); 493 | }), true).index; 494 | } 495 | 496 | export function sortedIndexOf(array: Array, value: any): number { 497 | let result: SearchResult = Algorithms.binarySearch(Collects.newArrayList(array), value, new ObjectComparator(), true); 498 | if (result.value == null) { 499 | return -1; 500 | } 501 | return result.index; 502 | } 503 | 504 | 505 | export function sortedLastIndex(array: Array, value: any): number { 506 | return Algorithms.binarySearch(Collects.newArrayList(array), value, new ObjectComparator(), false).index; 507 | } 508 | 509 | export function sortedLastIndexBy(array: Array, value: any, mapper: string | object | Array | Function): number { 510 | let m = _buildArrayMapper(mapper); 511 | let comparator: ObjectComparator = new ObjectComparator(); 512 | return Algorithms.binarySearch(Collects.newArrayList(array), value, new FunctionComparator((e1: any, e2: any) => { 513 | e1 = Functions.mapping(m, e1); 514 | e2 = Functions.mapping(m, e2); 515 | return comparator.compare(e1, e2); 516 | }), false).index; 517 | } 518 | 519 | export function sortedLastIndexOf(array: Array, value: any): number { 520 | let result: SearchResult = Algorithms.binarySearch(Collects.newArrayList(array), value, new ObjectComparator(), false); 521 | if (result.value == null) { 522 | return -1; 523 | } 524 | return result.index; 525 | } 526 | 527 | export function sortedUniq(array: Array): Array { 528 | return Collects.newTreeSet(array, new ObjectComparator()).toArray([]); 529 | } 530 | 531 | export function sortedUniqBy(array: Array, mapper: string | object | Array | Function) { 532 | let comparator: ObjectComparator = new ObjectComparator(); 533 | let m = _buildArrayMapper(mapper); 534 | return Collects.newTreeSet(array, new FunctionComparator((e1: any, e2: any) => { 535 | e1 = Functions.mapping(m, e1); 536 | e2 = Functions.mapping(m, e2); 537 | return comparator.compare(e1, e2); 538 | })).toArray([]); 539 | } 540 | 541 | export function tail(array: Array): Array { 542 | let length = Objects.getLength(array); 543 | if (length < 2) { 544 | return []; 545 | } 546 | return Pipeline.of(array).filter((element: any, index: number) => { 547 | return index > 0; 548 | }).toArray(); 549 | } 550 | 551 | export function take(array: Array, n: number): Array { 552 | return Pipeline.of(array).filter(truePredicate(), (element: any, index: number) => { 553 | return index >= n; 554 | }).toArray(); 555 | } 556 | 557 | export function takeRight(array: Array, n: number): Array { 558 | return Pipeline.of(array).reverse(true).filter((element: any, index: number) => { 559 | return index < n; 560 | }).toArray(); 561 | } 562 | 563 | export function takeWhile(array: Array, predicate: string | object | Array | Function): Array { 564 | let _predicate = _buildArrayPredicate(predicate); 565 | return Pipeline.of(array).filter(_predicate, (element: any, index: number) => { 566 | return !Functions.test(_predicate, element, index); 567 | }).toArray(); 568 | } 569 | 570 | export function takeRightWhile(array: Array, predicate: string | object | Array | Function): Array { 571 | let _predicate = _buildArrayPredicate(predicate); 572 | return Pipeline.of(array).reverse(true).filter(_predicate, (element: any, index: number) => { 573 | return !Functions.test(_predicate, element, index); 574 | }).toArray(); 575 | } 576 | 577 | export function union(array: Array>) { 578 | let set = Collects.newLinkedHashSet(); 579 | Collects.forEach(array, (element: Array) => { 580 | set.addAll(element); 581 | }, (element: Array) => { 582 | return element != null && Types.isCollection(element); 583 | }); 584 | return set.toArray(); 585 | } 586 | 587 | export function unionBy(array: Array>, mapper: string | object | Array | Function) { 588 | let comparator: ObjectComparator = new ObjectComparator(); 589 | let m = _buildArrayMapper(mapper); 590 | let set = Collects.newTreeSet(null, new FunctionComparator((e1: any, e2: any) => { 591 | e1 = Functions.mapping(m, e1); 592 | e2 = Functions.mapping(m, e2); 593 | comparator.compare(e1, e2); 594 | })); 595 | Collects.forEach(array, (element: Array) => { 596 | set.addAll(element); 597 | }, (element: Array) => { 598 | return element != null && Types.isCollection(element); 599 | }); 600 | return set.toArray(); 601 | } 602 | 603 | 604 | export function unionWith(array: Array>, comparator: Comparator | Function | Func2) { 605 | let _comparator: FunctionComparator = Comparators.functionComparator(comparator); 606 | let set = Collects.newTreeSet(null, _comparator); 607 | Collects.forEach(array, (element: Array) => { 608 | set.addAll(element); 609 | }, (element: Array) => { 610 | return element != null && Types.isCollection(element); 611 | }); 612 | return set.toArray(); 613 | } 614 | 615 | export function uniq(array: Array) { 616 | return Collects.newTreeSet(array, new IsComparator()).toArray([]); 617 | } 618 | 619 | export function uniqBy(array: Array, mapper: string | object | Array | Function) { 620 | let m = _buildArrayMapper(mapper); 621 | let comparator: ObjectComparator = new ObjectComparator(); 622 | return Collects.newTreeSet(array, new FunctionComparator((e1: any, e2: any) => { 623 | e1 = Functions.mapping(m, e1); 624 | e2 = Functions.mapping(m, e2); 625 | comparator.compare(e1, e2); 626 | })).toArray([]); 627 | } 628 | 629 | export function uniqWith(array: Array, comparator: Comparator | Function | Func2) { 630 | let _comparator: FunctionComparator = Comparators.functionComparator(comparator); 631 | return Collects.newTreeSet(array, _comparator).toArray([]); 632 | } 633 | 634 | export function unzip(arrays: Array>): Array> { 635 | if (Objects.isEmpty(arrays)) { 636 | return []; 637 | } 638 | let length = -1; 639 | Collects.forEach(arrays, function (array: Array) { 640 | throw new IllegalArgumentException("the length of every array is not equals"); 641 | }, function (array: Array) { 642 | if (!Types.isArray(array)) { 643 | return true; 644 | } 645 | let l = Objects.getLength(array); 646 | if (length != -1 && l !== length) { 647 | return true; 648 | } 649 | length = l; 650 | }); 651 | let result: Array> = []; 652 | for (let i = 0; i < length; i++) { 653 | let temp: Array = []; 654 | Collects.forEach(arrays, (array: Array) => { 655 | temp.push(array[i]); 656 | }); 657 | result.push(temp); 658 | } 659 | return result; 660 | } 661 | 662 | 663 | export function unzipWith(arrays: Array>, mapper: Function | Func2): Array { 664 | arrays = unzip(arrays); 665 | let result: Array = []; 666 | Collects.forEach(arrays, (array: Array) => { 667 | if (array.length > 0) { 668 | let tmp: any = array[0]; 669 | for (let i = 1; i < array.length; i++) { 670 | tmp = Functions.mapping(mapper, tmp, array[i]); 671 | } 672 | result.push(tmp); 673 | } else { 674 | result.push([]); 675 | } 676 | }); 677 | return result; 678 | } 679 | 680 | export function without(array: Array, values: Array) { 681 | let vs = Collects.newArrayList(values); 682 | Collects.removeIf(array, (element: any) => { 683 | return vs.contains(element); 684 | }, true); 685 | 686 | } 687 | 688 | export function xor(...arrays: Array): Array { 689 | let map: HashMap = Collects.newLinkedHashMap(); 690 | Pipeline.of(arrays).flatMap().forEach((element: any) => { 691 | let count = map.get(element); 692 | if (count == null) { 693 | map.put(element, 1); 694 | } else { 695 | map.put(element, ++count); 696 | } 697 | }); 698 | let result: Array = []; 699 | Collects.forEach(map, (entry: MapEntry) => { 700 | if (entry.value == 1) { 701 | result.push(entry.key); 702 | } 703 | }); 704 | return result; 705 | } 706 | 707 | export function xorBy(arrays: Array>, mapper: string | object | Array | Function): Array { 708 | let m = _buildArrayMapper(mapper); 709 | let mappedValueToOriginalValueMap: HashMap = Collects.newLinkedHashMap(); 710 | let map: HashMap = Collects.newLinkedHashMap(); 711 | Pipeline.of(arrays).flatMap().forEach((element: any) => { 712 | let mappedValue = Functions.mapping(m, element); 713 | if (!mappedValueToOriginalValueMap.containsKey(mappedValue)) { 714 | mappedValueToOriginalValueMap.put(mappedValue, element); 715 | } 716 | let count = map.get(mappedValue); 717 | if (count == null) { 718 | map.put(mappedValue, 1); 719 | } else { 720 | map.put(mappedValue, ++count); 721 | } 722 | }); 723 | let result: Array = []; 724 | Collects.forEach(map, (entry: MapEntry) => { 725 | if (entry.value == 1) { 726 | result.push(mappedValueToOriginalValueMap.get(entry.key)); 727 | } 728 | }); 729 | return result; 730 | } 731 | 732 | export function xorWith(arrays: Array>, comparator: Comparator | Func2 | Function): Array { 733 | let _comparator: FunctionComparator = Comparators.functionComparator(comparator); 734 | // mappedValue is the first occurs value 735 | let mappedValueToCountMap: HashMap = Collects.newLinkedHashMap(); 736 | Pipeline.of(arrays).flatMap().forEach((element: any) => { 737 | let mappedValue: any = Collects.findFirst(mappedValueToCountMap.keySet(), (mappedValue0: any) => { 738 | if (_comparator.compare(element, mappedValue0) == 0) { 739 | return mappedValue0; 740 | } 741 | }); 742 | if (mappedValue == null) { 743 | mappedValueToCountMap.put(element, 1); 744 | } else { 745 | let count = mappedValueToCountMap.get(mappedValue); 746 | mappedValueToCountMap.put(mappedValue, ++count); 747 | } 748 | }); 749 | let result: Array = []; 750 | Collects.forEach(mappedValueToCountMap, (entry: MapEntry) => { 751 | if (entry.value == 1) { 752 | result.push(entry.key); 753 | } 754 | }); 755 | return result; 756 | } 757 | 758 | export function zip(...arrays: Array): Array> { 759 | if (Objects.isEmpty(arrays)) { 760 | return []; 761 | } 762 | let length = -1; 763 | Collects.forEach(arrays, function (array: Array) { 764 | throw new IllegalArgumentException("the length of every array is not equals"); 765 | }, function (array: Array) { 766 | if (!Types.isArray(array)) { 767 | return true; 768 | } 769 | let l = Objects.getLength(array); 770 | if (length != -1 && l !== length) { 771 | return true; 772 | } 773 | length = l; 774 | }); 775 | let result: Array> = []; 776 | for (let i = 0; i < length; i++) { 777 | let temp: Array = []; 778 | Collects.forEach(arrays, (array: Array) => { 779 | temp.push(array[i]); 780 | }); 781 | result.push(temp); 782 | } 783 | return result; 784 | } -------------------------------------------------------------------------------- /src/main/logger.ts: -------------------------------------------------------------------------------- 1 | export function debug(...args: Array): void { 2 | console.debug(args); 3 | } 4 | 5 | export function info(...args: Array): void { 6 | console.log(args); 7 | } 8 | 9 | export function warn(...args: Array): void { 10 | console.warn(args); 11 | } 12 | 13 | export function error(...args: Array): void { 14 | console.error(args); 15 | } -------------------------------------------------------------------------------- /src/test/ts/Collects.test.ts: -------------------------------------------------------------------------------- 1 | import * as Types from "../../main/Types"; 2 | import * as Collects from "../../main/Collects"; 3 | import {ArrayList, HashMap, HashSet, LinkedList} from "../../main/Iterables"; 4 | import * as Pipeline from "../../main/Pipeline"; 5 | import * as Objects from "../../main/Objects"; 6 | 7 | /** 8 | * HelloWorld.test.ts 9 | */ 10 | describe("Collects tests", () => { 11 | 12 | test("cleanNulls", () => { 13 | debugger; 14 | let arrayList = Collects.asIterable(['a', '1', null, "x", new Date(), null, new Date().getTime(), "abc"]); 15 | expect(Pipeline.of(arrayList).cleanNulls().asList().size()).toBe(6); 16 | expect(Pipeline.of(arrayList).cleanNulls().findFirst()).toBe("a"); 17 | expect(Pipeline.of(arrayList).anyMatch((item) => { 18 | return Objects.isNull(item); 19 | })).toBe(true); 20 | expect(Pipeline.of(arrayList).cleanNulls().allMatch((item) => { 21 | return Objects.isNotNull(item); 22 | })).toBe(true); 23 | }); 24 | }); -------------------------------------------------------------------------------- /src/test/ts/Empty.test.ts: -------------------------------------------------------------------------------- 1 | import * as Emptys from "../../main/Emptys"; 2 | import {ArrayList, HashMap, HashSet, LinkedList} from "../../main/Iterables"; 3 | 4 | /** 5 | * HelloWorld.test.ts 6 | */ 7 | describe("Emptys tests", ()=>{ 8 | 9 | test('isNull', () => { 10 | debugger; 11 | expect(Emptys.isNull(null)).toBe(true); 12 | expect(Emptys.isNull(undefined)).toBe(true); 13 | expect(Emptys.isNull(3)).toBe(false); 14 | expect(Emptys.isNull({})).toBe(false); 15 | }); 16 | 17 | test("isEmpty", ()=>{ 18 | expect(Emptys.isEmpty(null)).toBe(true); 19 | expect(Emptys.isEmpty(undefined)).toBe(true); 20 | expect(Emptys.isEmpty([])).toBe(true); 21 | expect(Emptys.isEmpty({})).toBe(true); 22 | expect(Emptys.isEmpty(0)).toBe(true); 23 | expect(Emptys.isEmpty(2)).toBe(false); 24 | expect(Emptys.isEmpty({test:function (e) { 25 | 26 | }})).toBe(false); 27 | expect(Emptys.isEmpty(function () { 28 | 29 | })).toBe(false); 30 | expect(Emptys.isEmpty(new Set())).toBe(true); 31 | expect(Emptys.isEmpty(new Map())).toBe(true); 32 | expect(Emptys.isEmpty(new HashMap())).toBe(true); 33 | expect(Emptys.isEmpty(new ArrayList())).toBe(true); 34 | expect(Emptys.isEmpty(new LinkedList())).toBe(true); 35 | expect(Emptys.isEmpty(new HashSet())).toBe(true); 36 | }); 37 | 38 | }); 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/test/ts/List.test.ts: -------------------------------------------------------------------------------- 1 | import * as Collects from "../../main/Collects"; 2 | import * as logger from "../../main/logger"; 3 | import {List} from "../../main/Iterables"; 4 | /** 5 | * HelloWorld.test.ts 6 | */ 7 | describe("List Tests", ()=>{ 8 | 9 | function testList(list:List){ 10 | list.addAll(Collects.newArrayList(["a","b","c","d","e"])); 11 | Collects.forEach(list, (element)=>{ 12 | logger.info(element); 13 | }); 14 | debugger; 15 | expect(list.size()).toBe(5); 16 | list.add("f"); 17 | expect(list.size()).toBe(6); 18 | list.remove("f"); 19 | expect(list.size()).toBe(5); 20 | list.remove("f"); 21 | expect(list.size()).toBe(5); 22 | if(list.contains("a")){ 23 | logger.info("has 'a'"); 24 | } 25 | if(list.containsAll(Collects.newArrayList(["a","b"]))){ 26 | logger.info("contains ['a', 'b']"); 27 | } 28 | let alist:List = Collects.newArrayList(["a","b","k"]); 29 | if(!list.containsAll(alist)){ 30 | logger.info("not contains ['a', 'b','k']"); 31 | } 32 | list.removeAll(alist); 33 | expect(list.size()).toBe(3); 34 | expect(list.isEmpty()).toBe(false); 35 | list.retainAll(Collects.newArrayList(["c","d","m"])); 36 | expect(list.containsAll(Collects.newArrayList(["c","d"]))).toBe(true); 37 | expect(list.get(1)).toBe('d'); 38 | expect(list.get(0)).toBe('c'); 39 | } 40 | 41 | test("ArrayList Test", ()=>{ 42 | testList(Collects.emptyArrayList()); 43 | }); 44 | 45 | test("LinkedList Test", ()=>{ 46 | testList(Collects.emptyLinkedList()); 47 | }); 48 | }); -------------------------------------------------------------------------------- /src/test/ts/Map.test.ts: -------------------------------------------------------------------------------- 1 | import * as Collects from "../../main/Collects"; 2 | import * as logger from "../../main/logger"; 3 | import {LikeJavaMap, List} from "../../main/Iterables"; 4 | 5 | /** 6 | * HelloWorld.test.ts 7 | */ 8 | describe("Map Tests", () => { 9 | 10 | function testMap(map: LikeJavaMap) { 11 | debugger; 12 | 13 | Collects.forEach(Collects.newArrayList(["a", "b", "c", "d", "e"]), (element) => { 14 | map.put(element, null); 15 | }); 16 | Collects.forEach(map, (entry) => { 17 | logger.info(entry); 18 | }); 19 | Collects.forEach(map.keySet(), (key) => { 20 | logger.info(key); 21 | }); 22 | Collects.forEach(map.values(), (value) => { 23 | logger.info(value); 24 | }); 25 | expect(map.size()).toBe(5); 26 | map.put("f", null); 27 | expect(map.size()).toBe(6); 28 | map.remove("f"); 29 | expect(map.size()).toBe(5); 30 | map.remove("f"); 31 | expect(map.size()).toBe(5); 32 | if (map.containsKey("a")) { 33 | logger.info("has 'a'"); 34 | } 35 | let alist: List = Collects.newArrayList(["a", "b", "k"]); 36 | debugger 37 | Collects.removeIf(map, { 38 | test(key: string, value: any) { 39 | return alist.contains(key); 40 | } 41 | }); 42 | expect(map.size()).toBe(3); 43 | expect(map.isEmpty()).toBe(false); 44 | } 45 | 46 | test("LinkedHashMap Test", () => { 47 | testMap(Collects.emptyLinkedHashMap()); 48 | }); 49 | 50 | test("TreeMap Test", () => { 51 | testMap(Collects.emptyTreeMap()); 52 | }); 53 | 54 | test("HashMap Test", () => { 55 | testMap(Collects.emptyHashMap()); 56 | }); 57 | 58 | 59 | }); -------------------------------------------------------------------------------- /src/test/ts/Objects.test.ts: -------------------------------------------------------------------------------- 1 | import * as Objects from "../../main/Objects"; 2 | import * as logger from "../../main/logger"; 3 | /** 4 | * Objects.test.ts 5 | */ 6 | describe("Objects test", () => { 7 | 8 | test("TreeMap Test", () => { 9 | debugger; 10 | let obj = { 11 | "a":"a", 12 | b:"b" 13 | }; 14 | logger.info(Objects.hashCode(obj)); 15 | for(let key in obj){ 16 | logger.debug(key); 17 | } 18 | }); 19 | 20 | }); -------------------------------------------------------------------------------- /src/test/ts/Set.test.ts: -------------------------------------------------------------------------------- 1 | import * as Collects from "../../main/Collects"; 2 | import * as logger from "../../main/logger"; 3 | import {LikeJavaSet, List} from "../../main/Iterables"; 4 | /** 5 | * HelloWorld.test.ts 6 | */ 7 | describe("Set Tests", ()=>{ 8 | 9 | function testSet(list:LikeJavaSet){ 10 | debugger; 11 | list.addAll(Collects.newArrayList(["a","b","c","d","e"])); 12 | Collects.forEach(list, (element)=>{ 13 | logger.info(element); 14 | }); 15 | expect(list.size()).toBe(5); 16 | list.add("f"); 17 | expect(list.size()).toBe(6); 18 | list.remove("f"); 19 | expect(list.size()).toBe(5); 20 | list.remove("f"); 21 | expect(list.size()).toBe(5); 22 | if(list.contains("a")){ 23 | logger.info("has 'a'"); 24 | } 25 | if(list.containsAll(Collects.newArrayList(["a","b"]))){ 26 | logger.info("contains ['a', 'b']"); 27 | } 28 | let alist:List = Collects.newArrayList(["a","b","k"]); 29 | if(!list.containsAll(alist)){ 30 | logger.info("not contains ['a', 'b','k']"); 31 | } 32 | list.removeAll(alist); 33 | expect(list.size()).toBe(3); 34 | expect(list.isEmpty()).toBe(false); 35 | list.retainAll(Collects.newArrayList(["c","d","m"])); 36 | expect(list.containsAll(Collects.newArrayList(["c","d"]))).toBe(true); 37 | } 38 | 39 | test("LinkedHashSet Test", ()=>{ 40 | testSet(Collects.newLinkedHashSet()); 41 | }); 42 | 43 | test("HashSet Test", ()=>{ 44 | testSet(Collects.emptyHashSet()); 45 | }); 46 | 47 | test("Tree Test", ()=>{ 48 | testSet(Collects.emptyTreeSet()); 49 | }); 50 | 51 | }); -------------------------------------------------------------------------------- /src/test/ts/Types.test.ts: -------------------------------------------------------------------------------- 1 | import * as Types from "../../main/Types"; 2 | import {ArrayList, HashMap, HashSet, LinkedList} from "../../main/Iterables"; 3 | 4 | /** 5 | * HelloWorld.test.ts 6 | */ 7 | describe("Types tests", ()=>{ 8 | 9 | test("getType", ()=>{ 10 | debugger; 11 | expect(Types.getType(null)).toBe(undefined); 12 | expect(Types.getType(undefined)).toBe(undefined); 13 | expect(Types.getType([])).toBe(Array); 14 | expect(Types.getType({})).toBe(Object); 15 | expect(Types.getType(0)).toBe(Number); 16 | expect(Types.getType(2)).toBe(Number); 17 | expect(Types.getType({test:function (e) { 18 | 19 | }})).toBe(Object); 20 | expect(Types.getType(function () { 21 | 22 | })).toBe(Function); 23 | expect(Types.getType(new Set())).toBe(Set); 24 | expect(Types.getType(new Map())).toBe(Map); 25 | expect(Types.getType(new HashMap())).toBe(HashMap); 26 | expect(Types.getType(new ArrayList())).toBe(ArrayList); 27 | expect(Types.getType(new LinkedList())).toBe(LinkedList); 28 | expect(Types.getType(new HashSet())).toBe(HashSet); 29 | }); 30 | 31 | test("isFunction", ()=>{ 32 | expect(Types.isFunction(null)).toBe(false); 33 | expect(Types.isFunction(undefined)).toBe(false); 34 | expect(Types.isFunction([])).toBe(false); 35 | expect(Types.isFunction({})).toBe(false); 36 | expect(Types.isFunction(0)).toBe(false); 37 | expect(Types.isFunction(2)).toBe(false); 38 | expect(Types.isFunction({test:function (e) { 39 | 40 | }})).toBe(false); 41 | expect(Types.isFunction(function () { 42 | 43 | })).toBe(true); 44 | expect(Types.isFunction(new Set())).toBe(false); 45 | expect(Types.isFunction(new Map())).toBe(false); 46 | expect(Types.isFunction(new HashMap())).toBe(false); 47 | expect(Types.isFunction(new ArrayList())).toBe(false); 48 | expect(Types.isFunction(new LinkedList())).toBe(false); 49 | expect(Types.isFunction(new HashSet())).toBe(false); 50 | }); 51 | 52 | }); 53 | -------------------------------------------------------------------------------- /tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "target": "ES2015", 6 | "outDir": "./dist/cjs" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "ESNEXT", 5 | "importHelpers": true, 6 | "target": "ES2015", 7 | "outDir": "./dist/esm" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "charset": "utf8", 5 | "noImplicitAny": false, 6 | "strict": false, 7 | "removeComments": true, 8 | "moduleResolution": "node", 9 | "pretty": true, 10 | "allowJs": true, 11 | "checkJs": true, 12 | "traceResolution":true, 13 | "suppressImplicitAnyIndexErrors" : false, 14 | "strictNullChecks": true, 15 | "strictPropertyInitialization": true, 16 | "noUnusedLocals": false, 17 | "noUnusedParameters": false, 18 | "downlevelIteration": true 19 | }, 20 | "include": [ 21 | "src/main/**/*" 22 | ], 23 | "exclude": [ 24 | "node_modules", 25 | "**/*.spec.ts" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /tsconfig.types.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.esm.json", 3 | "compilerOptions": { 4 | "module": "ES2015", 5 | "target": "ESNEXT", 6 | "removeComments": false, 7 | "declaration": true, 8 | "declarationMap": true, 9 | "declarationDir": "./dist/types" 10 | } 11 | } 12 | --------------------------------------------------------------------------------