{"id":15045345,"url":"https://github.com/lanternpowered/lmbda","last_synced_at":"2025-04-10T00:43:02.010Z","repository":{"id":95663442,"uuid":"145303551","full_name":"LanternPowered/Lmbda","owner":"LanternPowered","description":"A lambda factory.","archived":false,"fork":false,"pushed_at":"2025-03-09T21:00:36.000Z","size":468,"stargazers_count":28,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"3.x","last_synced_at":"2025-04-10T00:42:56.306Z","etag":null,"topics":["fast-reflection","field","field-lambda","field-lambda-factory","java","java-11","java-17","java-21","java-8","java-8-lambda","java-9","kotlin","lambda","lambda-factory","reflection"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LanternPowered.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-19T13:01:34.000Z","updated_at":"2025-04-08T12:11:18.000Z","dependencies_parsed_at":"2023-10-17T05:44:21.761Z","dependency_job_id":"a3d00294-aef2-46ff-abe1-a70d63d9ca23","html_url":"https://github.com/LanternPowered/Lmbda","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LanternPowered%2FLmbda","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LanternPowered%2FLmbda/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LanternPowered%2FLmbda/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LanternPowered%2FLmbda/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LanternPowered","download_url":"https://codeload.github.com/LanternPowered/Lmbda/tar.gz/refs/heads/3.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248137998,"owners_count":21053775,"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":["fast-reflection","field","field-lambda","field-lambda-factory","java","java-11","java-17","java-21","java-8","java-8-lambda","java-9","kotlin","lambda","lambda-factory","reflection"],"created_at":"2024-09-24T20:51:45.621Z","updated_at":"2025-04-10T00:43:01.998Z","avatar_url":"https://github.com/LanternPowered.png","language":"Java","readme":"## Lmbda [![Discord](https://img.shields.io/badge/chat-on%20discord-6E85CF.svg)](https://discord.gg/ArSrsuU) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.lanternpowered/lmbda/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.lanternpowered/lmbda)\n\nThis is library that can be used to generate lambdas from method handles with any kind of \naccess modifier without any performance loss. This includes methods, constructors, field accessors \n(getter, setter) and any other [`MethodHandle`] that can be constructed.\n\n❗ **Note**: Since Java 23, `MethodHandleProxies.asInterfaceInstance(...)` has been re-written and performance is now in \nline with direct access and lmbda implementations. It might be worth looking into that method instead to avoid adding \nnew dependencies. However, not all features like abstract functional classes will be supported.\n\n* [Source]\n* [Issues]\n\n[Source]: https://github.com/LanternPowered/Lmbda\n[Issues]: https://github.com/LanternPowered/Lmbda/issues\n\n[`MethodHandle`]: https://docs.oracle.com/javase/10/docs/api/java/lang/invoke/MethodHandle.html\n[`MethodHandles#privateLookupIn`]: https://docs.oracle.com/javase/10/docs/api/java/lang/invoke/MethodHandles.html#privateLookupIn(java.lang.Class,java.lang.invoke.MethodHandles.Lookup)\n\n## How to use\n\nEvery available `MethodHandle` can be implemented by a functional interface. But only if the two method signatures match. Object types will be auto\ncasted to the target type if possible, the same goes for boxing/unboxing of primitive types.\n\nNon-static methods will always take an extra parameter which represents the target object of the method. This is always the first parameter.\n\nNote: Generating functions requires that you have access to the target class.\nSince Java 9, this is even more important because the module your code is located in must be able to access the module of the target class, see\n [`MethodHandles#privateLookupIn`] for more info.\n\n### Generating method functions\n\n#### Static setter method\n\nConsider the following class which holds a static setter function.\n```java\nclass MyObject {\n    private static void set(int value) {\n        // ...\n    }\n}\n```\nIf you want to generate a function for the static `set(int)` method, you need to use\na interface which takes one parameter (`value`) and return `void` to reflect\nthe method signature. The `IntConsumer` is a good choice available within the\nJava 8 API.\n\n```java\nfinal MethodHandles.Lookup lookup = MethodHandlesExtensions.privateLookupIn(MyObject.class, MethodHandles.lookup());\nfinal MethodHandle methodHandle = lookup.findStatic(MyObject.class, \"set\", MethodType.methodType(void.class, int.class));\n\nfinal IntConsumer setter = LambdaFactory.create(LambdaType.of(IntConsumer.class), methodHandle);\nsetter.accept(1000);\n```\n\n#### Setter method\n\nConsider the following class which holds a setter function.\n```java\nclass MyObject {\n    private void set(int value) {\n        // ...\n    }\n}\n```\n\nIf you want to generate a function for the static `set(int)` method, you need to use\na interface which takes two parameters:\n\n1. The target of where the method is declared, this will be the target object on which the method is invoked. E.g. `target.set(value)`\n2. The value that will be passed to the `set` method.\n\nthe first one is the target where the method is declared, `MyObject` (`value`) and return `void` to reflect\nthe method signature. The `ObjIntConsumer` is a good choice available within the Java 8 API.\n\n```java\nfinal MethodHandles.Lookup lookup = MethodHandlesExtensions.privateLookupIn(MyObject.class, MethodHandles.lookup());\nfinal MethodHandle methodHandle = lookup.findVirtual(MyObject.class, \"set\", MethodType.methodType(void.class, int.class));\n\nfinal ObjIntConsumer\u003cMyObject\u003e setter = LambdaFactory.create(new LambdaType\u003cObjIntConsumer\u003cMyObject\u003e\u003e() {}, methodHandle);\n\nfinal MyObject myObject = new MyObject();\nsetter.accept(myObject, 1000);\n```\n\n\n## Benchmarks\n\nBelow you can find a few benchmarks. `lmbda` will be generated at runtime, all the other\nones are implemented manually. The generated structure of the `lmbda` is almost the\nsame as the `static_mh`.\n\nThe following benchmark implements a lambda function to access a `int` field, a `ToIntFunction`\nis implemented in this case to avoid boxing/unboxing.\n\nThe benchmark was run on an AMD Ryzen 9 5900X CPU and using JDK 16.0.2\n\nBenchmark                                   | Mode | Cnt | Score | Error | Units\n--------------------------------------------|:----:|:---:|:-----:|:-----:|:----:\nIntGetterFieldBenchmark.direct              | avgt | 15 | 1.304 | ± 0.008 | ns/op\nIntGetterFieldBenchmark.fieldConst          | avgt | 15 | 2.698 | ± 0.061 | ns/op\nIntGetterFieldBenchmark.fieldDyn            | avgt | 15 | 2.986 | ± 0.005 | ns/op\nIntGetterFieldBenchmark.lmbda               | avgt | 15 | 1.299 | ± 0.005 | ns/op\nIntGetterFieldBenchmark.methodHandleConst   | avgt | 15 | 1.300 | ± 0.004 | ns/op\nIntGetterFieldBenchmark.methodHandleDyn     | avgt | 15 | 3.013 | ± 0.018 | ns/op\nIntGetterFieldBenchmark.methodHandleProxy   | avgt | 15 | 7.530 | ± 0.185 | ns/op\nIntGetterFieldBenchmark.plain               | avgt | 15 | 1.304 | ± 0.006 | ns/op\n\n\nThis benchmark returns a `Integer` through the `getValue` method from a target object.\n\nBenchmark                                  | Mode | Cnt | Score | Error | Units\n-------------------------------------------|:----:|:---:|:-----:|:-----:|:----:\nIntGetterMethodBenchmark.direct            | avgt | 15 | 1.372 | ± 0.003 | ns/op\nIntGetterMethodBenchmark.lambdaMetafactory | avgt | 15 | 1.387 | ± 0.024 | ns/op\nIntGetterMethodBenchmark.lmbda             | avgt | 15 | 1.370 | ± 0.004 | ns/op\nIntGetterMethodBenchmark.methodConst       | avgt | 15 | 3.731 | ± 0.106 | ns/op\nIntGetterMethodBenchmark.methodDyn         | avgt | 15 | 4.164 | ± 0.139 | ns/op\nIntGetterMethodBenchmark.methodHandleConst | avgt | 15 | 1.612 | ± 0.379 | ns/op\nIntGetterMethodBenchmark.methodHandleDyn   | avgt | 15 | 3.852 | ± 0.116 | ns/op\nIntGetterMethodBenchmark.methodHandleProxy | avgt | 15 | 8.085 | ± 0.070 | ns/op\nIntGetterMethodBenchmark.plain             | avgt | 15 | 1.398 | ± 0.025 | ns/op\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flanternpowered%2Flmbda","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flanternpowered%2Flmbda","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flanternpowered%2Flmbda/lists"}