Skip to content

Commit 4099462

Browse files
committed
Sync with underscore-java
1 parent 82e7c69 commit 4099462

File tree

5 files changed

+95
-0
lines changed

5 files changed

+95
-0
lines changed

src/main/java/com/github/underscore/U.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,11 @@ public <F> Chain<Map<F, List<T>>> groupBy(final Function<T, F> func) {
367367
return new Chain<>(Underscore.groupBy(value(), func));
368368
}
369369

370+
@Override
371+
public <F> Chain<Map<F, T>> associateBy(final Function<T, F> func) {
372+
return new Chain<>(Underscore.associateBy(value(), func));
373+
}
374+
370375
@Override
371376
public <F> Chain<Map<F, Optional<T>>> groupBy(
372377
final Function<T, F> func, final BinaryOperator<T> binaryOperator) {

src/main/java/com/github/underscore/Underscore.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,21 @@ public <K, E> Map<K, Optional<E>> groupBy(
10461046
return groupBy((Iterable<E>) iterable, func, binaryOperator);
10471047
}
10481048

1049+
public static <K, E> Map<K, E> associateBy(
1050+
final Iterable<E> iterable, final Function<E, K> func) {
1051+
final Map<K, E> retVal = newLinkedHashMap();
1052+
for (E e : iterable) {
1053+
final K key = func.apply(e);
1054+
retVal.putIfAbsent(key, e);
1055+
}
1056+
return retVal;
1057+
}
1058+
1059+
@SuppressWarnings("unchecked")
1060+
public <K, E> Map<K, E> associateBy(final Function<E, K> func) {
1061+
return associateBy((Iterable<E>) iterable, func);
1062+
}
1063+
10491064
@SuppressWarnings("unchecked")
10501065
public static <K, E> Map<K, List<E>> indexBy(
10511066
final Iterable<E> iterable, final String property) {
@@ -3000,6 +3015,10 @@ public <F> Chain<Map<F, List<T>>> groupBy(final Function<T, F> func) {
30003015
return new Chain<>(Underscore.groupBy(list, func));
30013016
}
30023017

3018+
public <F> Chain<Map<F, T>> associateBy(final Function<T, F> func) {
3019+
return new Chain<>(Underscore.associateBy(list, func));
3020+
}
3021+
30033022
public <F> Chain<Map<F, Optional<T>>> groupBy(
30043023
final Function<T, F> func, final BinaryOperator<T> binaryOperator) {
30053024
return new Chain<>(Underscore.groupBy(list, func, binaryOperator));

src/test/java/com/github/underscore/CollectionsTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,26 @@ void groupBy() {
14361436
assertEquals("{1.0=[1.3], 2.0=[2.1, 2.4]}", resultChain.toString());
14371437
}
14381438

1439+
/*
1440+
_.associateBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
1441+
=> {1: [1.3], 2: [2.1, 2.4]}
1442+
*/
1443+
@Test
1444+
@SuppressWarnings("unchecked")
1445+
void associateBy() {
1446+
final Map<Double, Double> result =
1447+
Underscore.associateBy(asList(1.3, 2.1, 2.4), Math::floor);
1448+
assertEquals("{1.0=1.3, 2.0=2.1}", result.toString());
1449+
final Map<Double, Double> resultObj =
1450+
new Underscore(asList(1.3, 2.1, 2.4))
1451+
.associateBy((Function<Double, Double>) Math::floor);
1452+
assertEquals("{1.0=1.3, 2.0=2.1}", resultObj.toString());
1453+
final Map<Double, Double> resultChain =
1454+
(Map<Double, Double>)
1455+
Underscore.chain(asList(1.3, 2.1, 2.4)).associateBy(Math::floor).item();
1456+
assertEquals("{1.0=1.3, 2.0=2.1}", resultChain.toString());
1457+
}
1458+
14391459
/*
14401460
_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
14411461
=> {1: [1.3], 2: [2.1, 2.4]}

src/test/java/com/github/underscore/LodashTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,6 +1780,7 @@ void chain() {
17801780
U.chain(new Integer[] {0}).sortBy(value -> value);
17811781
U.chain(new LinkedHashMap<Integer, Integer>().entrySet()).sortBy("");
17821782
U.chain(new Integer[] {0}).groupBy(value -> value);
1783+
U.chain(new Integer[] {0}).associateBy(value -> value);
17831784
U.chain(new Integer[] {0}).groupBy(num -> num, (a, b) -> a);
17841785
U.chain(new Integer[] {0}).indexBy("");
17851786
U.chain(new Integer[] {0}).countBy(value -> value);

src/test/java/com/github/underscore/StringTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3552,6 +3552,56 @@ void fromXmlStackoverflowObject() throws IOException {
35523552
}
35533553
}
35543554

3555+
private String repeat(String s, int times) {
3556+
StringBuilder stringBuilder = new StringBuilder(s.length() * times);
3557+
for (int i = 0; i < times; i++) {
3558+
stringBuilder.append(s);
3559+
}
3560+
return stringBuilder.toString();
3561+
}
3562+
3563+
@SuppressWarnings("unchecked")
3564+
@Test
3565+
void testParseDeeplyNestedArrays() throws IOException {
3566+
int times = 1000;
3567+
// [[[ ... ]]]
3568+
String json = repeat("[", times) + repeat("]", times);
3569+
3570+
int actualTimes = 0;
3571+
List<Object> current = U.fromJson(json);
3572+
while (true) {
3573+
actualTimes++;
3574+
if (current.isEmpty()) {
3575+
break;
3576+
}
3577+
assertEquals(1, current.size());
3578+
current = (List<Object>) current.get(0);
3579+
}
3580+
assertEquals(times, actualTimes);
3581+
}
3582+
3583+
@SuppressWarnings("unchecked")
3584+
@Test
3585+
void testParseDeeplyNestedObjects() throws IOException {
3586+
int times = 1000;
3587+
// {"a":{"a": ... {"a":null} ... }}
3588+
String json = repeat("{\"a\":", times) + "null" + repeat("}", times);
3589+
3590+
int actualTimes = 0;
3591+
Map<String, Object> current = U.fromJsonMap(json);
3592+
while (true) {
3593+
assertEquals(1, current.size());
3594+
actualTimes++;
3595+
Map<String, Object> next = (Map<String, Object>) current.get("a");
3596+
if (next == null) {
3597+
break;
3598+
} else {
3599+
current = next;
3600+
}
3601+
}
3602+
assertEquals(times, actualTimes);
3603+
}
3604+
35553605
@Test
35563606
void testDecodeParseXmlErr13() {
35573607
assertThrows(IllegalArgumentException.class, () -> U.fromXml("[\"abc\u0010\"]"));

0 commit comments

Comments
 (0)