Skip to content

Instantly share code, notes, and snippets.

@SvaponiAkelius
Created July 1, 2019 16:30
Show Gist options
  • Save SvaponiAkelius/1390a1a40ab50c154ead73963daa3f54 to your computer and use it in GitHub Desktop.
Save SvaponiAkelius/1390a1a40ab50c154ead73963daa3f54 to your computer and use it in GitHub Desktop.
Java utils (deep copy, map merge, to/from hexadecimal string)
public class Utils {
public static <T> T deepCopy(final T object) {
try {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final ObjectOutputStream outputStrm = new ObjectOutputStream(outputStream);
outputStrm.writeObject(object);
final ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
final ObjectInputStream objInputStream = new ObjectInputStream(inputStream);
return (T) objInputStream.readObject();
} catch (final Exception e) {
e.printStackTrace();
return null;
}
}
/**
* @param mvm multi-value map
* @return single-value map (when size > 1, value = original list; when size == 0, value = null)
*/
public static Map<String, Object> toLightweightMap(final MultiValueMap<String, Object> mvm) {
return mvm.entrySet().stream()
.filter(e -> e.getValue() != null)
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().size() == 0 ? null : e.getValue().size() == 1 ? e.getValue().get(0) : e.getValue(), (a, b) -> a == null ? b : a));
}
/**
* deep merges all values from two maps (including nested maps).
* values from #oldMap will be replaced with values from #newMap in case the key already exists
*
* @param target base map
* @param source contains new data for old map (which will be added to old map)
* @return #oldMap containing all additional values from #newMap
*/
public static Map<String, Object> merge(final Map<String, Object> target, final Map<String, Object> source) {
final Map<String, Object> oldCopy = Utils.deepCopy(target);
mergeWithSideEffect(oldCopy, source);
return oldCopy;
}
/**
* @param target original map, the one with the side effect
* @param source source map, the one with new data to be merged into #target
* @throws UnsupportedOperationException when #target contains a collection that does not allow add op
*/
public static void mergeWithSideEffect(final Map<String, Object> target, final Map<String, Object> source) throws UnsupportedOperationException {
source.forEach((key, sourceObj) -> {
final Object targetObj = target.get(key);
if (sourceObj instanceof Map && targetObj instanceof Map) {
mergeWithSideEffect((Map) targetObj, (Map) sourceObj);
} else if (sourceObj instanceof Collection && targetObj instanceof Collection) {
mergeWithSideEffect((Collection) targetObj, (Collection) sourceObj);
} else {
target.put(key, sourceObj);
}
});
}
/**
* @param target original collection, the one with the side effect
* @param source source collection, the one with new data to be merged into #target
* @throws UnsupportedOperationException when #target does not allow add op
*/
public static void mergeWithSideEffect(final Collection target, final Collection source) throws UnsupportedOperationException {
source.stream()
.filter(item -> !target.contains(item))
.forEach(target::add);
}
/**
* same as {@link java.util.Arrays#asList(Object[])} but returns a mutable list
*/
public static <T> List<T> asMutableList(final T... a) {
return new ArrayList<>(Arrays.asList(a));
}
public static String toHex(final String text) {
return new BigInteger(1, text.getBytes(Charset.defaultCharset())).toString(16);
}
public static String fromHex(final String hex) {
return new String(new BigInteger(hex, 16).toByteArray());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment