Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions .github/workflows/github-packages-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
name: Publish Packages to GitHub Packages with Gradle

on:
push:
branches:
- main
release:
types:
- published

jobs:
build:
Expand Down Expand Up @@ -51,19 +51,17 @@ jobs:
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'corretto'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
java-version: "17"
distribution: "corretto"

- name: Setup Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
uses: gradle/actions/setup-gradle@v4

- name: Grant Execution Authority to Gradlew
run: chmod +x ./gradlew

- name: Build with Gradle
run: ./gradlew build
run: ./gradlew build -PartefactVersion=${{ github.event.release.tag_name }} # Overwrite artefactVersion

- name: Publish to Maven Central
run: ./gradlew publish
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

package com.onixbyte.devkit.utils;

import java.util.Arrays;
import java.util.Objects;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
Expand Down Expand Up @@ -89,62 +88,50 @@ private BranchUtil(boolean result) {
* Creates a {@code BranchUtil} instance to evaluate a logical OR operation on the provided
* boolean expressions.
*
* @param booleans the boolean expressions to be evaluated
* @param <T> the type of the result to be handled by the methods
* @param values the boolean expressions to be evaluated
* @param <T> the type of the result to be handled by the methods
* @return a {@code BranchUtil} instance representing the result of the logical OR operation
*/
public static <T> BranchUtil<T> or(Boolean... booleans) {
var result = Arrays.stream(booleans)
.filter(Objects::nonNull)
.anyMatch(Boolean::booleanValue);
return new BranchUtil<>(result);
public static <T> BranchUtil<T> or(Boolean... values) {
return new BranchUtil<>(BoolUtil.or(values));
}

/**
* Creates a {@code BranchUtil} instance to evaluate a logical AND operation on the provided
* boolean expressions.
*
* @param booleans the boolean expressions to be evaluated
* @param <T> the type of the result to be handled by the methods
* @param values the boolean expressions to be evaluated
* @param <T> the type of the result to be handled by the methods
* @return a {@code BranchUtil} instance representing the result of the logical AND operation
*/
public static <T> BranchUtil<T> and(Boolean... booleans) {
var result = Arrays.stream(booleans)
.filter(Objects::nonNull)
.allMatch(Boolean::booleanValue);
return new BranchUtil<>(result);
public static <T> BranchUtil<T> and(Boolean... values) {
return new BranchUtil<>(BoolUtil.and(values));
}

/**
* Creates a {@code BranchUtil} instance to evaluate a logical OR operation on the provided
* boolean suppliers.
*
* @param booleanSuppliers the boolean suppliers to be evaluated
* @param <T> the type of the result to be handled by the methods
* @param valueSuppliers the boolean suppliers to be evaluated
* @param <T> the type of the result to be handled by the methods
* @return a {@code BranchUtil} instance representing the result of the
* logical OR operation
*/
public static <T> BranchUtil<T> or(BooleanSupplier... booleanSuppliers) {
var result = Arrays.stream(booleanSuppliers)
.filter(Objects::nonNull)
.anyMatch(BooleanSupplier::getAsBoolean);
return new BranchUtil<>(result);
public static <T> BranchUtil<T> or(BooleanSupplier... valueSuppliers) {
return new BranchUtil<>(BoolUtil.or(valueSuppliers));
}

/**
* Creates a {@code BranchUtil} instance to evaluate a logical AND operation on the provided
* boolean suppliers.
*
* @param booleanSuppliers the boolean suppliers to be evaluated
* @param <T> the type of the result to be handled by the methods
* @param valueSuppliers the boolean suppliers to be evaluated
* @param <T> the type of the result to be handled by the methods
* @return a {@code BranchUtil} instance representing the result of the
* logical AND operation
*/
public static <T> BranchUtil<T> and(BooleanSupplier... booleanSuppliers) {
var result = Arrays.stream(booleanSuppliers)
.filter(Objects::nonNull)
.allMatch(BooleanSupplier::getAsBoolean);
return new BranchUtil<>(result);
public static <T> BranchUtil<T> and(BooleanSupplier... valueSuppliers) {
return new BranchUtil<>(BoolUtil.and(valueSuppliers));
}

/**
Expand Down
17 changes: 8 additions & 9 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,17 @@
# limitations under the License.
#

jacksonVersion=2.17.2
jacksonVersion=2.18.0
javaJwtVersion=4.4.0
jjwtVersion=0.12.6
junitVersion=5.10.2
logbackVersion=1.5.4
lombokVersion=1.18.30
slf4jVersion=2.0.9
springVersion=6.1.3
springBootVersion=3.2.3
junitVersion=5.11.2
logbackVersion=1.5.10
lombokVersion=1.18.34
slf4jVersion=2.0.16
springVersion=6.1.13
springBootVersion=3.3.4

buildGroupId=com.onixbyte
buildVersion=1.6.4
buildVersion=1.6.5
projectUrl=https://onixbyte.com/JDevKit
projectGithubUrl=https://github.com/OnixByte/JDevKit
licenseName=The Apache License, Version 2.0
Expand Down
19 changes: 19 additions & 0 deletions num4j/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
id("java")
}

group = "com.onixbyte"
version = "unspecified"

repositories {
mavenCentral()
}

dependencies {
testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks.test {
useJUnitPlatform()
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

package com.onixbyte.devkit.utils;
package com.onixbyte.nums;

import lombok.Getter;

Expand Down Expand Up @@ -87,7 +87,7 @@
*
* @author sunzsh
* @version 1.1.0
* @see java.math.BigDecimal
* @see BigDecimal
* @since 1.0.0
*/
@Getter
Expand Down
106 changes: 106 additions & 0 deletions num4j/src/main/java/com/onixbyte/nums/PercentileCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (C) 2024 OnixByte.
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*/
package com.onixbyte.nums;

import com.onixbyte.nums.model.QuartileBounds;

import java.util.List;

/**
* A utility class that provides methods for calculating percentiles and interquartile range (IQR) bounds
* for a dataset.
* <p>
* This class contains static methods to:
* <ul>
* <li>Calculate a specified percentile from a list of double values using linear interpolation.</li>
* <li>Calculate interquartile bounds (Q1, Q3) and the corresponding lower and upper bounds,
* which can be used to identify outliers in the dataset.</li>
* </ul>
* <p>
* This class is final, meaning it cannot be subclassed, and it only contains static methods,
* so instances of the class cannot be created.
* </p>
* <h2>Example usage:</h2>
* <pre>
* {@code
* List<Double> data = Arrays.asList(1.0, 2.0, 3.0, 4.0, 5.0);
* Double percentileValue = PercentileCalculator.calculatePercentile(data, 50.0); // Calculates median
* QuartileBounds bounds = PercentileCalculator.calculatePercentileBounds(data); // Calculates IQR bounds
* }
* </pre>
*
* @author zihluwang
* @version 1.6.5
* @since 1.6.5
*/
public final class PercentileCalculator {

/**
* Calculates the specified percentile from a list of values.
* <p>
* This method takes a list of double values and calculates the given percentile using linear interpolation between
* the two closest ranks. The list is first sorted in ascending order, and the specified percentile is
* then calculated.
*
* @param values a list of {@code Double} values from which the percentile is calculated.
* @param percentile a {@code Double} representing the percentile to be calculated (e.g., 50.0 for the median)
* @return a {@code Double} value representing the calculated percentile
*/
public static Double calculatePercentile(List<Double> values, Double percentile) {
var sorted = values.stream().sorted().toList();
if (sorted.isEmpty()) {
throw new IllegalArgumentException("Unable to sort an empty list.");
}

var rank = percentile / 100. * (sorted.size() - 1);
var lowerIndex = (int) Math.floor(rank);
var upperIndex = (int) Math.ceil(rank);
var weight = rank - lowerIndex;

return sorted.get(lowerIndex) * (1 - weight) + sorted.get(upperIndex) * weight;
}

/**
* Calculates the interquartile range (IQR) and the corresponding lower and upper bounds
* based on the first (Q1) and third (Q3) quartiles of a dataset.
* <p>
* This method takes a list of double values, calculates the first quartile (Q1),
* the third quartile (Q3), and the interquartile range (IQR). Using the IQR, it computes
* the lower and upper bounds, which can be used to detect outliers in the dataset.
* The lower bound is defined as {@code Q1 - 1.5 * IQR}, and the upper bound is defined as
* {@code Q3 + 1.5 * IQR}.
*
* @param data a list of {@code Double} values for which the quartile bounds will be calculated
* @return a {@code QuartileBounds} object containing the calculated lower and upper bounds
*/
public static QuartileBounds calculatePercentileBounds(List<Double> data) {
var sorted = data.stream().sorted().toList();
var Q1 = calculatePercentile(sorted, 25.);
var Q3 = calculatePercentile(sorted, 75.);

var IQR = Q3 - Q1;

var lowerBound = Q1 - 1.5 * IQR;
var upperBound = Q3 + 1.5 * IQR;

return QuartileBounds.builder()
.upperBound(upperBound)
.lowerBound(lowerBound)
.build();
}

}
Loading