Install
$ agentstack add skill-kyu-n-gdx-claude-skills-libgdx-collections-json ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
libGDX Collections, Pooling, JSON & Utilities
Quick reference for com.badlogic.gdx.utils.* — libGDX's GC-friendly collections, object pooling, JSON serialization, and utility classes. These replace java.util.* equivalents to reduce garbage collection pressure, especially on Android.
Array\ — ArrayList Replacement
Array arr = new Array<>(); // also: new Array<>(capacity), new Array<>(ordered, capacity)
Public fields: T[] items (backing array), int size (element count), boolean ordered.
Key methods: add, get, set, insert, swap, pop, peek, first, clear, sort, reverse, shuffle, truncate, shrink, ensureCapacity, isEmpty, notEmpty, select(predicate).
CRITICAL — identity parameter required: removeValue(item, identity), contains(item, identity), indexOf(item, identity), lastIndexOf(item, identity). identity=true uses ==, identity=false uses .equals(). There is no single-argument overload.
There is NO remove(Object) method. It is removeValue(value, identity) or removeIndex(int).
Gotchas:
itemsarray may be larger thansize— iterate with `for (int i = 0; i / SnapshotArray\
Both wrap begin()/end() around iteration. DelayedRemovalArray queues removals during iteration, applies at end() (returns void from begin()). SnapshotArray takes a snapshot; begin() returns T[] to iterate, modifications go to a copy. Both support nested begin()/end(). Used internally by Scene2D.
ObjectMap\ — HashMap Replacement
ObjectMap map = new ObjectMap<>();
map.put("hp", 100); // returns old value or null
map.get("hp"); map.get("hp", 0); // null or default
map.remove("hp"); map.containsKey("hp");
map.containsValue(100, false); // identity param on values too
size is a public field (not a method). Iterate via for (Entry e : map), map.keys(), map.values(), or map.entries().
Gotchas:
- Same Entry instance is reused on each
next()call. Do not store entry references. - Iterators are pooled by default (
Collections.allocateIterators = false). Nested iteration on the same map throwsGdxRuntimeException. SetCollections.allocateIterators = trueif needed. - There is no
entrySet()/keySet()— useentries(),keys(),values()(libGDX iterator types).
OrderedMap\ — extends ObjectMap, maintains insertion order. orderedKeys() returns internal Array.
Primitive-Key Maps (Avoid Boxing)
IntMap, LongMap — object values, get() returns null if missing. IntIntMap, ObjectIntMap, ObjectFloatMap — primitive values, get() MUST provide default (no null for primitives). ObjectIntMap has getAndIncrement(key, defaultValue, increment).
Primitive-value maps: put() returns void (not old value). Use put(key, value, defaultValue) overload to get old value.
Sets
ObjectSet — add, remove, contains (NO identity param, unlike Array). first() throws if empty. OrderedSet — maintains insertion order, orderedItems() returns internal Array. IntSet — primitive int, does NOT implement Iterable. size is a public field on all sets.
Queue\ — Double-Ended Queue
addLast/addFirst, removeFirst/removeLast, first()/last() (peek), get(index). size is a public field.
Pooling
Pool\ and DefaultPool\
Pool is abstract — override newObject(). Methods: obtain(), free(obj) (calls reset() if Pool.Poolable), fill(n), getFree(), clear(). Constructor: Pool(initialCapacity, max).
DefaultPool\ (since 1.13.5) — preferred. Uses supplier: new DefaultPool<>(Bullet::new) or new DefaultPool<>(Bullet::new, 16, 100). No reflection, GWT-safe.
Implement Pool.Poolable for automatic reset() on free().
PoolManager — Shared Pool Registry (since 1.14.0)
PoolManager pools = new PoolManager();
pools.addPool(Bullet.class, Bullet::new); // or pass a Pool directly
Bullet b = pools.obtain(Bullet.class);
pools.free(b); // looks up pool by object's class
Deprecated Pooling APIs
- DO NOT use
ReflectionPool(deprecated 1.13.5) — useDefaultPool. - DO NOT use
Pools(deprecated 1.14.0) — useDefaultPoolorPoolManager.
JSON
Json — Serializer/Deserializer
Json json = new Json();
json.setOutputType(JsonWriter.OutputType.json); // json | javascript | minimal
json.setIgnoreUnknownFields(true); // don't fail on extra fields
json.setUsePrototypes(false); // write all fields, not just changed
String str = json.toJson(myObject); // serialize
MyClass obj = json.fromJson(MyClass.class, jsonStr); // deserialize (also accepts FileHandle)
There is no Json.parse() method. Use JsonReader for raw parsing or Json.fromJson() for typed deserialization.
Custom serializer: json.setSerializer(MyClass.class, new Json.Serializer() { ... }) — implement write(Json, T, Class) and read(Json, JsonValue, Class).
JsonReader — Raw Parsing to Tree
new JsonReader().parse(fileHandle) or .parse(string) returns JsonValue tree.
JsonValue — DOM Tree Navigation
Navigation: get("name") / get(index) returns child JsonValue (null if not found). has("name"), size (public field). Type checks: isObject(), isArray(), isString(), isNumber(), isBoolean(), isNull().
as* vs get* — CRITICAL distinction:
asString(),asInt(),asFloat(),asBoolean()— converts THIS node's value.getString("name"),getInt("hp")— finds child by name, returns its value. ThrowsIllegalArgumentExceptionif child not found. UsegetString("name", "default")for safe defaults.
Iterate children: for (JsonValue entry : root) { entry.name; entry.asString(); } or for (JsonValue c = root.child; c != null; c = c.next).
I18NBundle — Localization
I18NBundle.createBundle(fileHandle) or createBundle(fileHandle, locale). Methods: get("key"), format("key", args...). Resolution: messages_de_DE.properties → messages_de.properties → messages.properties.
There is no I18NBundle.load() — use the static factory I18NBundle.createBundle().
Timer
// Static convenience (uses global Timer.instance())
Timer.schedule(new Timer.Task() {
public void run() { /* runs on GL thread */ }
}, 2f); // delay seconds
Timer.schedule(task, 1f, 0.5f); // delay, then repeat every 0.5s forever
Timer.schedule(task, 1f, 0.5f, 5); // delay, interval, repeatCount
task.cancel(); // cancel a scheduled task
task.isScheduled(); // boolean
Timer.Task is abstract — override run(). run() executes on the GL/render thread (posted via Gdx.app.postRunnable()), safe for libGDX API calls.
Instance methods use scheduleTask(task, ...) (not schedule). The timer also has stop(), start(), clear().
Other Utilities
TimeUtils:
long start = TimeUtils.nanoTime();
// ... work ...
long elapsed = TimeUtils.timeSinceNanos(start); // nanoTime() - start
long ms = TimeUtils.millis(); // System.currentTimeMillis()
long elapsedMs = TimeUtils.timeSinceMillis(startMs);
Align — bit-flag constants for layout alignment:
Align.center // 1 Align.topLeft // top|left
Align.top // 2 Align.topRight // top|right
Align.bottom // 4 Align.bottomLeft // bottom|left
Align.left // 8 Align.bottomRight // bottom|right
Align.right // 16
Scaling — abstract class with static instances (NOT an enum): Scaling.fit, Scaling.fill, Scaling.contain, Scaling.stretch, Scaling.fillX, Scaling.fillY, Scaling.stretchX, Scaling.stretchY, Scaling.none.
AsyncExecutor — simple thread pool:
AsyncExecutor executor = new AsyncExecutor(4); // 4 threads
AsyncResult result = executor.submit(() -> computeExpensiveThing());
if (result.isDone()) {
String value = result.get(); // blocks if not done, throws on error
}
executor.dispose(); // MUST dispose
AsyncTask interface has a single T call() method. Executor must be disposed.
ScreenUtils:
ScreenUtils.clear(0, 0, 0, 1); // r, g, b, a
ScreenUtils.clear(Color.BLACK);
ScreenUtils.clear(0, 0, 0, 1, true); // also clear depth buffer
GWT Compatibility
libGDX collections are GWT-compatible while many java.util features are not. Prefer libGDX collections in cross-platform projects. For reflection on GWT, use com.badlogic.gdx.utils.reflect.* instead of java.lang.reflect.*.
Common Mistakes
- Using
java.util.ArrayList/HashMap/HashSet— UseArray,ObjectMap,ObjectSetinstead. libGDX collections reduce GC pressure and are GWT-compatible. - Omitting the
identityparameter —Array.contains(),indexOf(),removeValue(), andObjectMap.containsValue()require a booleanidentityparameter.true= use==,false= use.equals(). There is no single-argument overload. - Using
array.items.lengthinstead ofarray.size—items.lengthis the backing array capacity. Elements pastsizeare stale. Always usesize. - Calling
Array.remove(object)— This method does not exist. UseremoveValue(object, identity)orremoveIndex(int). - Iterating ObjectMap with
map.entrySet()— Does not exist. Usemap.entries(),map.keys(),map.values(), orfor (Entry e : map)directly. Same Entry instance is reused each iteration — do not store references. - Nested iteration on the same map — By default, iterators are pooled. Nested iteration throws
GdxRuntimeException. SetCollections.allocateIterators = trueto allow it. - Using
Pools.obtain()/ReflectionPool— Both deprecated (1.14.0 / 1.13.5). Usenew DefaultPool<>(MyClass::new)for local pools orPoolManagerfor shared pools. - Calling
pool.obtain()withoutpool.free()— Defeats the purpose of pooling. Always pair obtain/free, ideally in try/finally. - Calling
Json.parse()— Does not exist. UseJsonReader.parse()for rawJsonValuetree, orJson.fromJson()for typed deserialization. - Confusing
getString("name")withasString()on JsonValue —getString("name")finds a child named "name" and returns its string value.asString()returns THIS node's value. CallinggetString()on a node without matching children throwsIllegalArgumentException. - Assuming Timer runs on a background thread —
Timer.Task.run()executes on the GL/render thread viapostRunnable(). Safe for libGDX API calls but do not block it. - Using
I18NBundle.load()— Does not exist. Use the static factoryI18NBundle.createBundle().
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: kyu-n
- Source: kyu-n/gdx-claude-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.