{"id":21007100,"url":"https://github.com/jjfiv/chai","last_synced_at":"2025-05-15T02:31:20.410Z","repository":{"id":31665554,"uuid":"35230970","full_name":"jjfiv/chai","owner":"jjfiv","description":"Opinionated, mostly-tested, modern and simple Java utilities.","archived":false,"fork":false,"pushed_at":"2023-03-06T00:56:21.000Z","size":557,"stargazers_count":4,"open_issues_count":7,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-03-12T10:11:38.083Z","etag":null,"topics":["java","utility"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jjfiv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-07T16:27:19.000Z","updated_at":"2021-12-27T14:56:41.000Z","dependencies_parsed_at":"2023-01-14T19:30:58.390Z","dependency_job_id":null,"html_url":"https://github.com/jjfiv/chai","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjfiv%2Fchai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjfiv%2Fchai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjfiv%2Fchai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjfiv%2Fchai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jjfiv","download_url":"https://codeload.github.com/jjfiv/chai/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225324174,"owners_count":17456458,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","utility"],"created_at":"2024-11-19T08:54:55.827Z","updated_at":"2024-11-19T08:54:56.314Z","avatar_url":"https://github.com/jjfiv.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Chai \n![CI](https://github.com/jjfiv/chai/workflows/Java%20CI%20with%20Maven/badge.svg)\n\n*Because I don't like coffee, but I like Java. Mostly.*\n\n## About\n\nThe Java standard libraries are amazing. When I pull out a ``ConcurrentHashMap``, I know I'm standing on the shoulders of giants. There are other great libraries like [GNU Trove](http://trove.starlight-systems.com/), which add pieces that are missing to the standard libraries (primitive collections) but don't necessarily play nice with the interfaces in the standard JDK.\n\nAnother way to put it is that in my work I need the raw performance and I prefer the typing of Java, but I'm really jealous of [Clojure's standard library](http://clojure.github.io/clojure/clojure.core-api.html).\n\nChai is a lightweight, well-tested, opinionated library that builds on some of the really nice interfaces and tools built into the JDK that makes my coding and prototyping a lot easier and simpler.\n\n## About TL;DR\n\nEveryone has their own library of utility functions. Mine's just better tested than most.\n\n## Version Support\n\nSupports Java 8 and above. I love default methods on interfaces and lambdas in general. I have Github Actions double-checking my commits so that I don't break anything.\n\n## Documentation\n\nThis is a tough one. I'm going to figure out how to build and push javadoc somewhere soon, but until then, check out some of the tests for an example of some of the useful static functions provided by Chai.\n\nUntil then, some favorites:\n```java\n// Chai provides wrapper types that allow chaining:\nassertEquals(\n  Arrays.asList(10, 20, 30),\n  ChaiMap.create(\n    Pair.of(1, 10),\n    Pair.of(2, 20),\n    Pair.of(3, 30)\n\t).readOnly().vals().sorted().intoList());\n```\n\nOr if you ever just really need a simple \"group-by\" operation. Note that this plays nice with existing JVM types, like ``List\u003cT\u003e`` and ``Iterable\u003cT\u003e``.\n\n```java\npublic static \u003cK,T\u003e Map\u003cK, List\u003cT\u003e\u003e groupBy(Iterable\u003cT\u003e data, TransformFn\u003cT,K\u003e makeKeyFn) {\n  Map\u003cK, List\u003cT\u003e\u003e grouped = new HashMap\u003c\u003e();\n  for (T t : data) {\n    MapFns.extendListInMap(grouped, makeKeyFn.transform(t), t);\n  }\n  return grouped;\n}\n```\n## Include in Maven\n\nTo add the [jitpack.io maven repo](https://jitpack.io/) to your maven repos:\n```xml \n \t\u003crepositories\u003e\n\t\t\u003crepository\u003e\n\t\t    \u003cid\u003ejitpack.io\u003c/id\u003e\n\t\t    \u003curl\u003ehttps://jitpack.io\u003c/url\u003e\n\t\t\u003c/repository\u003e\n\t\u003c/repositories\u003e\n```\n\nTo add this dependency:\n```xml\n\t\u003cdependency\u003e\n\t    \u003cgroupId\u003ecom.github.jjfiv\u003c/groupId\u003e\n\t    \u003cartifactId\u003echai\u003c/artifactId\u003e\n\t    \u003cversion\u003ev0.9\u003c/version\u003e\n\t\u003c/dependency\u003e\n```\n\n## History\n\n### v0.9\n - SortedReader, MergeSortedReader (for disk-based merge-sorting)\n - ArrayFns.reverse\n - StreamingStats.isEmpty\n - ClassDataDirectory\n - LinesIterable.progressForEach, ListFns.findAll, IntList.from(int...)\n - StrUtil.wordWrap -\u003e List\u003cString\u003e (Not perfect)\n - depend on Galago utility\n - StrUtil.containsLetterOrDigit\n - IntList::last\n - Debouncer.estimateStr(i,total) to choose which estimate to use\n - public check to see if heap is full\n - UserData::hasUserData(Class\u003c?\u003e klazz)\n - CLI\n - ListFns.slice\n - IntList::pushAll(IntList)\n - IntLIst::forEach(TIntProcedure) leaning on trove here\n - process spawning (Spawn)\n - ClassifierInfo::getPostiiveF scores\n - SetFns for trove\n - ListFns now return ArrayList if important\n - IntervalTree\u003cT\u003e from Apache Cassandra\n - FullStats public\n - fast nextBoolean\n - TopKHeap::takeTop(TObjectIntHashMap\u003cT\u003e)\n - HTTPUtil\n - InputContainer::estimateCount\n - StrUtil::replaceAny\n - AUC.computeAP\n - IO.resource now nullable output\n - AUC.compute() from Wikipedia, SciKit Learn\n - Perceptron : Classifier\n - WebServer, JSONAPI support hostname\n - MString mutable string\n - remove .size on IntList\n - SetFns.difference\n - IntList.removeInt(); to avoid boxing and confusion\n - AChaiList::chooseRandomly\n - IntList.shuffle\n - StrUtil.looksLikeInt\n - CLI.readString\n\n### v0.8\n - InputFinder, TarIterator\n - Java v8\n - CircularIntBuffer\n - IntList.encode, decode\n - LinesIterable counts line numbers\n - Directory.Read\n - Nonnull fixes\n - ListFns.slice\n - ShardedTextWriter\n - Directory.ls\n - Directory.isEmpty\n - IterableFns.sortedStreamingGroupBy\n - StrUtil.slice\n - ListFns.lazyMap\n - Debouncer for time-limited messages\n - IntList.push(int)\n - StrUtil.join\n - IntList.sort()\n - LZFCodec\n - MemoryNotifier.pollMemoryUsage\n - TopKHeap.peek() is now @Nullable\n - FixedSlidingWindow\u003cT\u003e for circular buffer\n - ReservoirSampler\u003cT\u003e\n - BitVector\n - IO.spit(bytes, file)\n - ListFns.map\n - StreamFns.hasMoreData() works with PushBackInputStream and InputStreams that have mark() and reset() impl.\n - ListFns.partition(list, 1) faster\n - ReducingIterator, LazyReduceFn\n - IntList.equals, IntList.hashCode faster\n - trove4j wrappers in MapFactory (@Beta)\n - QuickSort.sort(cmp, keys[], values[])\n - StreamingStats::add\n - InputContainer::isParallel\n - DoubleList like IntList, DoubleList.toStats()\n - MapFns.getOrInsert()\n - StrUtil.collapseSpecialMarks()\n - IntRange.intersects(IntRange)\n - ``TopKHeap.getTotalSeen() -\u003e long``\n - TopKHeap.clear\n - ListFns.fill(size, index -\u003e ?)\n - ``StringIntHashMap @Beta``\n - StrUtil.takeBeforeLast, StrUtil.takeAfterLast\n - LinesIterable.slurp\n - NibbleList\n - chai-web JSONAPI, depends on galago:utility\n - InputStreamable.lines isa LinesIterable\n - Weighted\u003cT\u003e in TopKHeap helper object\n - IntList final fixes\n - PMIObject\u003cT\u003e\n - UserData class-based map\n - StrUtil.substr() like ListFns.slice\n - StreamingStats.pushAll(List\u003cDouble\u003e)\n\n\n### v0.5\n - ``StreamStat``\n - ``finalize()`` in Temporary cleanup to find errors\n - ``extendListInMap`` more efficient\n - ``ListFns.getLast(list)``\n - NonNull\n - ``Pair.getBestComparator()``\n - ``StreamFns.readChannel()`` returns a ``ByteBuffer``\n - ``Sample.letters``\n - ``ListFns.repeatUntilAtLeast``\n\n### v0.4\n - Annotations: ``@Beta``, for classes that aren't ready, ``EmergencyUseOnly``, for methods that ought to be private but aren't.\n - Start using findbugs jsr305 ``@Nullable`` and ``@Nonnull``\n - ``IntList.resize()``\n - ``MapFns.extendCollectionInMap()`` takes a ``GenerateFn\u003cColl\u003e`` rather than a collection, so that it doesn't wastefully allocate on each call even if the collection is not needed.\n - ``Require.that()``, for when you're not sure assertions are on\n - handle some unicode quotes in ``StrUtil``\n - ``long|Pair\u003cLong,T\u003e Timing.milliseconds(Runnable|GenerateFn\u003cT\u003e)``\n - ``ListFns.slice()``\n - ``ListBasedOrderedSet.toList()``\n - ``ListFns.zip()``\n - ``ListFns.unique()``\n - ``MapFns.fromPairs()``\n - ``ListFnsTest`` catchup\n - Add useful constructor to ``ListBasedOrderedSet``, and fix associated bugs.\n - remove newlines from preview, create a ``MemoryNotifier`` class, ``ThreadsafeLazyPtr``, ``ListFns.maxBy``\n - Fix/Break ``Pair`` comparators to not super ``Map.Entry`` anymore.\n - ``ZipWriter instanceof Flushable``\n - ``QuickSort`` implementation which avoids copying, has wildcarded comparators.\n - ``Builder\u003cT\u003e`` marker interface for things with ``T getOutput()``\n - ``TemporaryDirectory instanceof Directory, GenerateFn\u003cFile\u003e``\n - ``IO.openOutputStream(File|String)``\n - ``IOTest``\n - better error message if you try to use a default comparator on something that isn't comparable.\n - ``wrapInputStream`` paving the way for compressed files inside archives, for instance\n - add a quick ``FS.isDirectory`` for when you don't care about the file object afterward.\n - ``IO.resource(String name)``, ``IO.resourceStream(String name)``, and ``IO.slurp(InputStream)``\n - ``StrUtil.indent(text, tabChars)``\n\n\n### v0.3\n - ``TemporaryDirectory``\n - ``ZipWriter``\n - ``IntMath::fromLong``\n - ``Closer\u003cT\u003e implements GenerateFn\u003cT\u003e { T get(); }``\n - ``Comparing.byteArrays()``\n - ``ArrayFns.compare(byte[], byte[])``\n - Scattered Javadocs and Tests\n\n### v0.2\n - ``StreamFns``\n    - ``readBytes``\n    - ``fromByteBuffer``\n    - ``readAll``\n - More reader factories on ``IO``\n - ``DoubleFns.equals(a,b,epsilon)``\n - ``ZipArchive, ZipArchiveEntry``\n - ``LazyPtr\u003cT\u003e``\n - ``ListFns.partition`` and ``ListFns.roundRobinPartition``\n - ``MapFns.getOrElse``\n - indenting, tests, javadoc\n\n### v0.1\n - XML as a separate module\n - ``TreeFns``\n - ``AChaiList`` is a superset of ``AbstractList`` functionality\n - ``ChaiIterable`` isa ``Collection``\n - ``TopKHeap`` has ``addAll`` and ``bool offer()``\n - Move to github and setup travis\n - ... implement and pull in from other files.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjjfiv%2Fchai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjjfiv%2Fchai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjjfiv%2Fchai/lists"}