diff --git a/xapi-client/src/main/java/dev/learning/xapi/client/StatementHttpMessageWriter.java b/xapi-client/src/main/java/dev/learning/xapi/client/StatementHttpMessageWriter.java index 2969fe99..71fc305e 100644 --- a/xapi-client/src/main/java/dev/learning/xapi/client/StatementHttpMessageWriter.java +++ b/xapi-client/src/main/java/dev/learning/xapi/client/StatementHttpMessageWriter.java @@ -188,10 +188,15 @@ private List getParts(Object object) { */ private Stream getRealAttachments(Statement statement) { + Stream stream; + // handle the rare scenario when a sub-statement has an attachment - var stream = statement.getObject() instanceof final SubStatement substatement - && substatement.getAttachments() != null ? substatement.getAttachments().stream() - : Stream.empty(); + if (statement.getObject() instanceof final SubStatement substatement + && substatement.getAttachments() != null) { + stream = substatement.getAttachments().stream(); + } else { + stream = Stream.empty(); + } if (statement.getAttachments() != null) { stream = Stream.concat(stream, statement.getAttachments().stream()); diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/Attachment.java b/xapi-model/src/main/java/dev/learning/xapi/model/Attachment.java index dcca1fdf..0a831db3 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/Attachment.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/Attachment.java @@ -210,11 +210,10 @@ private static String sha256Hex(byte[] data) { final var hash = digest.digest(data); final var hexString = new StringBuilder(2 * hash.length); for (final byte element : hash) { - final var hex = Integer.toHexString(0xff & element); - if (hex.length() == 1) { - hexString.append('0'); - } - hexString.append(hex); + // Use bitwise operations to avoid string allocation per byte + final int value = 0xff & element; + hexString.append(Character.forDigit(value >>> 4, 16)); + hexString.append(Character.forDigit(value & 0x0f, 16)); } return hexString.toString(); } diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/LanguageMap.java b/xapi-model/src/main/java/dev/learning/xapi/model/LanguageMap.java index 5db5af6f..b94824a7 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/LanguageMap.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/LanguageMap.java @@ -26,6 +26,11 @@ public class LanguageMap extends LinkedHashMap { private static final long serialVersionUID = 7375610804995032187L; + /** + * Cached undefined locale instance to avoid repeated object creation. + */ + private static final Locale UNDEFINED_LOCALE = new Locale("und"); + /** * Constructs an empty LanguageMap. */ @@ -49,7 +54,7 @@ public LanguageMap(Map languageMap) { * @param value to be added with the undefined locale as a key */ public void put(String value) { - this.put(new Locale("und"), value); + this.put(UNDEFINED_LOCALE, value); } /** @@ -83,15 +88,15 @@ public String get(List languageRanges) { } // Otherwise return UND - final var und = get(new Locale("und")); + final var und = get(UNDEFINED_LOCALE); if (und != null) { return und; } // Otherwise return first - final var first = keySet().stream().findFirst(); - if (first.isPresent()) { - return get(first.get()); + final var iterator = keySet().iterator(); + if (iterator.hasNext()) { + return get(iterator.next()); } // Map must be empty diff --git a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java index 907866d4..bb246a33 100644 --- a/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java +++ b/xapi-model/src/main/java/dev/learning/xapi/model/validation/internal/validators/MboxValidator.java @@ -21,12 +21,14 @@ public class MboxValidator extends DisableableValidator { public static final String PREFIX = "mailto:"; - EmailValidator emailValidator; + /** + * Cached email validator instance to avoid repeated object creation. + */ + private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator(); @Override public void initialize(Mbox mbox) { - - emailValidator = new EmailValidator(); + // No initialization needed - using static validator } @Override @@ -36,7 +38,7 @@ public boolean isValidIfEnabled(String value, ConstraintValidatorContext context } return value.startsWith(PREFIX) - && emailValidator.isValid(value.substring(PREFIX.length()), context); + && EMAIL_VALIDATOR.isValid(value.substring(PREFIX.length()), context); } }