Skip to content

Commit

Permalink
- nextPermutation() added to MathUtilities
Browse files Browse the repository at this point in the history
- size(), isEmpty(), and hasContent() added to CollectionUtilities
  • Loading branch information
jdereg committed Jun 1, 2024
1 parent 911c505 commit 42287b4
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 31 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<groupId>com.cedarsoftware</groupId>
<artifactId>java-util</artifactId>
<packaging>bundle</packaging>
<version>2.9.0</version>
<version>2.10.0</version>
<description>Java Utilities</description>
<url>https://github.com/jdereg/java-util</url>

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/cedarsoftware/util/ByteUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public static String encode(final byte[] bytes)
*
* @param value
* to be converted
* @return '0'..'F' in char format.
* @return '0'...'F' in char format.
*/
private static char convertDigit(final int value)
{
Expand Down
62 changes: 53 additions & 9 deletions src/main/java/com/cedarsoftware/util/CollectionUtilities.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,73 @@
package com.cedarsoftware.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
* @author John DeRegnaucourt ([email protected])
* <br>
* Copyright (c) Cedar Software LLC
* <br><br>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <br><br>
* <a href="http://www.apache.org/licenses/LICENSE-2.0">License</a>
* <br><br>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class CollectionUtilities {

private static final Set<?> unmodifiableEmptySet = Collections.unmodifiableSet(new HashSet<>());

private static final List<?> unmodifiableEmptyList = Collections.unmodifiableList(new ArrayList<>());

/**
* This is a null-safe isEmpty check.
*
* @param col Collection to check
* @return true if empty or null
*/
public static boolean isEmpty(Collection col) {
return col == null || col.isEmpty();
}

/**
* This is a null-safe isEmpty check.
*
* @param col Collection to check
* @return true if empty or null
*/
public static boolean hasContent(Collection col) {
return col != null && !col.isEmpty();
}

/**
* This is a null-safe size check.
*
* @param col Collection to check
* @return true if empty or null
*/
public static int size(Collection col) {
return col == null ? 0 : col.size();
}

/**
* For JDK1.8 support. Remove this and change to List.of() for JDK11+
*/
@SafeVarargs
public static <T> List<T> listOf(T... items)
{
if (items == null || items.length ==0)
{
return (List<T>)unmodifiableEmptyList;
public static <T> List<T> listOf(T... items) {
if (items == null || items.length == 0) {
return (List<T>) unmodifiableEmptyList;
}
List<T> list = new ArrayList<>();
Collections.addAll(list, items);
Expand All @@ -32,10 +78,8 @@ public static <T> List<T> listOf(T... items)
* For JDK1.8 support. Remove this and change to Set.of() for JDK11+
*/
@SafeVarargs
public static <T> Set<T> setOf(T... items)
{
if (items == null || items.length ==0)
{
public static <T> Set<T> setOf(T... items) {
if (items == null || items.length == 0) {
return (Set<T>) unmodifiableEmptySet;
}
Set<T> set = new LinkedHashSet<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@
*/
public class EncryptionUtilities
{
private EncryptionUtilities()
{
}
private EncryptionUtilities() { }

/**
* Super-fast MD5 calculation from entire file. Uses FileChannel and
Expand Down
31 changes: 30 additions & 1 deletion src/main/java/com/cedarsoftware/util/MathUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;

import static java.util.Collections.swap;

/**
* Useful Math utilities
Expand Down Expand Up @@ -292,4 +295,30 @@ public static Number parseToMinimalNumericType(String numStr) {
}
}
}
}

/**
* Utility method for generating the "next" permutation.
* @param list List of integers, longs, etc. Typically, something like [1, 2, 3, 4] and it
* will generate the next permutation [1, 2, 4, 3]. It will override the passed in
* list. This way, each call to nextPermutation(list) works, until it returns false,
* much like an Iterator.
*/
static <T extends Comparable<? super T>> boolean nextPermutation(List<T> list) {
int k = list.size() - 2;
while (k >= 0 && list.get(k).compareTo(list.get(k + 1)) >= 0) {
k--;
}
if (k < 0) {
return false; // No more permutations
}
int l = list.size() - 1;
while (list.get(k).compareTo(list.get(l)) >= 0) {
l--;
}
swap(list, k, l);
for (int i = k + 1, j = list.size() - 1; i < j; i++, j--) {
swap(list, i, j);
}
return true;
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/cedarsoftware/util/SealableList.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

/**
* SealableList provides a List or List wrapper that can be 'sealed' and 'unsealed.' When
* sealed, the List is mutable, when unsealed it is immutable (read-only). The iterator(),
* sealed, the List is immutable, when unsealed it is mutable. The iterator(),
* listIterator(), and subList() return views that honor the Supplier's sealed state.
* The sealed state can be changed as often as needed.
* <br><br>
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/com/cedarsoftware/util/StringUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.util.Optional;
import java.util.Random;

import static java.lang.Character.toLowerCase;

/**
* Useful String utilities for common tasks
*
Expand Down Expand Up @@ -165,7 +167,7 @@ static boolean regionMatches(CharSequence cs, boolean ignoreCase, int thisStart,
// The real same check as in String.regionMatches():
char u1 = Character.toUpperCase(c1);
char u2 = Character.toUpperCase(c2);
if (u1 != u2 && Character.toLowerCase(u1) != Character.toLowerCase(u2)) {
if (u1 != u2 && toLowerCase(u1) != toLowerCase(u2)) {
return false;
}
}
Expand Down Expand Up @@ -623,10 +625,10 @@ public static int hashCodeIgnoreCase(String s) {
if (s == null) {
return 0;
}
int len = s.length();
final int len = s.length();
int hash = 0;
for (int i = 0; i < len; i++) {
hash = 31 * hash + Character.toLowerCase((int) s.charAt(i));
hash = 31 * hash + toLowerCase(s.charAt(i));
}
return hash;
}
Expand Down
78 changes: 66 additions & 12 deletions src/test/java/com/cedarsoftware/util/CollectionUtilitiesTests.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
package com.cedarsoftware.util;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.jupiter.api.Test;

import static com.cedarsoftware.util.CollectionUtilities.hasContent;
import static com.cedarsoftware.util.CollectionUtilities.isEmpty;
import static com.cedarsoftware.util.CollectionUtilities.listOf;
import static com.cedarsoftware.util.CollectionUtilities.setOf;
import static com.cedarsoftware.util.CollectionUtilities.size;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* @author John DeRegnaucourt ([email protected])
* <br>
* Copyright (c) Cedar Software LLC
* <br><br>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <br><br>
* <a href="http://www.apache.org/licenses/LICENSE-2.0">License</a>
* <br><br>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class CollectionUtilitiesTests {
static class Rec {
final String s;
Expand All @@ -28,35 +53,35 @@ static class Rec {

@Test
void testListOf() {
final List<String> list = CollectionUtilities.listOf();
final List<String> list = listOf();
assertEquals(0, list.size());
}

@Test
void testListOf_producesImmutableList() {
final List<String> list = CollectionUtilities.listOf();
final List<String> list = listOf();
assertThatExceptionOfType(UnsupportedOperationException.class)
.isThrownBy(() -> list.add("One"));
}

@Test
void testListOfOne() {
final List<String> list = CollectionUtilities.listOf("One");
final List<String> list = listOf("One");
assertEquals(1, list.size());
assertEquals("One", list.get(0));
}

@Test
void testListOfTwo() {
final List<String> list = CollectionUtilities.listOf("One", "Two");
final List<String> list = listOf("One", "Two");
assertEquals(2, list.size());
assertEquals("One", list.get(0));
assertEquals("Two", list.get(1));
}

@Test
void testListOfThree() {
final List<String> list = CollectionUtilities.listOf("One", "Two", "Three");
final List<String> list = listOf("One", "Two", "Three");
assertEquals(3, list.size());
assertEquals("One", list.get(0));
assertEquals("Two", list.get(1));
Expand All @@ -65,39 +90,68 @@ void testListOfThree() {

@Test
void testSetOf() {
final Set<?> set = CollectionUtilities.setOf();
final Set<?> set = setOf();
assertEquals(0, set.size());
}

@Test
void testSetOf_producesImmutableSet() {
final Set<String> set = CollectionUtilities.setOf();
final Set<String> set = setOf();
assertThatExceptionOfType(UnsupportedOperationException.class)
.isThrownBy(() -> set.add("One"));
}


@Test
void testSetOfOne() {
final Set<String> set = CollectionUtilities.setOf("One");
final Set<String> set = setOf("One");
assertEquals(1, set.size());
assertTrue(set.contains("One"));
}

@Test
public void testSetOfTwo() {
final Set<String> set = CollectionUtilities.setOf("One", "Two");
void testSetOfTwo() {
final Set<String> set = setOf("One", "Two");
assertEquals(2, set.size());
assertTrue(set.contains("One"));
assertTrue(set.contains("Two"));
}

@Test
public void testSetOfThree() {
final Set<String> set = CollectionUtilities.setOf("One", "Two", "Three");
void testSetOfThree() {
final Set<String> set = setOf("One", "Two", "Three");
assertEquals(3, set.size());
assertTrue(set.contains("One"));
assertTrue(set.contains("Two"));
assertTrue(set.contains("Three"));
}

@Test
void testIsEmpty() {
assertTrue(isEmpty(null));
assertTrue(isEmpty(new ArrayList<>()));
assertTrue(isEmpty(new HashSet<>()));
assertFalse(isEmpty(setOf("one")));
assertFalse(isEmpty(listOf("one")));
}

@Test
void testHasContent() {
assertFalse(hasContent(null));
assertFalse(hasContent(new ArrayList<>()));
assertFalse(hasContent(new HashSet<>()));
assertTrue(hasContent(setOf("one")));
assertTrue(hasContent(listOf("one")));
}

@Test
void testSize() {
assertEquals(0, size(null));
assertEquals(0, size(new ArrayList<>()));
assertEquals(0, size(new HashSet<>()));
assertEquals(1, size(setOf("one")));
assertEquals(1, size(listOf("one")));
assertEquals(2, size(setOf("one", "two")));
assertEquals(2, size(listOf("one", "two")));
}
}

0 comments on commit 42287b4

Please sign in to comment.