JAVA-12097: renamed algorithms-module to algorithms-modules
This commit is contained in:
4
algorithms-modules/algorithms-miscellaneous-3/.gitignore
vendored
Normal file
4
algorithms-modules/algorithms-miscellaneous-3/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/target/
|
||||
.settings/
|
||||
.classpath
|
||||
.project
|
||||
17
algorithms-modules/algorithms-miscellaneous-3/README.md
Normal file
17
algorithms-modules/algorithms-miscellaneous-3/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
## Algorithms - Miscellaneous
|
||||
|
||||
This module contains articles about algorithms. Some classes of algorithms, e.g., [sorting](/algorithms-sorting) and
|
||||
[genetic algorithms](/algorithms-genetic), have their own dedicated modules.
|
||||
|
||||
## Relevant Articles:
|
||||
|
||||
- [Java Two Pointer Technique](https://www.baeldung.com/java-two-pointer-technique)
|
||||
- [Implementing Simple State Machines with Java Enums](https://www.baeldung.com/java-enum-simple-state-machine)
|
||||
- [Converting Between Roman and Arabic Numerals in Java](https://www.baeldung.com/java-convert-roman-arabic)
|
||||
- [Practical Java Examples of the Big O Notation](https://www.baeldung.com/java-algorithm-complexity)
|
||||
- [Checking If a List Is Sorted in Java](https://www.baeldung.com/java-check-if-list-sorted)
|
||||
- [Checking if a Java Graph has a Cycle](https://www.baeldung.com/java-graph-has-a-cycle)
|
||||
- [A Guide to the Folding Technique in Java](https://www.baeldung.com/folding-hashing-technique)
|
||||
- [Creating a Triangle with for Loops in Java](https://www.baeldung.com/java-print-triangle)
|
||||
- [The K-Means Clustering Algorithm in Java](https://www.baeldung.com/java-k-means-clustering-algorithm)
|
||||
- More articles: [[<-- prev]](/algorithms-miscellaneous-2) [[next -->]](/algorithms-miscellaneous-4)
|
||||
70
algorithms-modules/algorithms-miscellaneous-3/pom.xml
Normal file
70
algorithms-modules/algorithms-miscellaneous-3/pom.xml
Normal file
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>algorithms-miscellaneous-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>algorithms-miscellaneous-3</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>algorithms-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>${commons-collections4.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>retrofit</artifactId>
|
||||
<version>${retrofit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>converter-jackson</artifactId>
|
||||
<version>${retrofit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>pl.pragmatists</groupId>
|
||||
<artifactId>JUnitParams</artifactId>
|
||||
<version>${JUnitParams.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
<version>${jmh-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh-generator.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-bytecode</artifactId>
|
||||
<version>${jmh-generator.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<retrofit.version>2.6.0</retrofit.version>
|
||||
<JUnitParams.version>1.1.0</JUnitParams.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.baeldung.algorithms.checksortedlist;
|
||||
|
||||
public class Employee {
|
||||
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
public Employee() {
|
||||
}
|
||||
|
||||
public Employee(long id, String name) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.baeldung.algorithms.checksortedlist;
|
||||
|
||||
import static org.apache.commons.collections4.CollectionUtils.isEmpty;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Comparators;
|
||||
import com.google.common.collect.Ordering;;
|
||||
|
||||
public class SortedListChecker {
|
||||
|
||||
private SortedListChecker() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static boolean checkIfSortedUsingIterativeApproach(List<String> listOfStrings) {
|
||||
if (isEmpty(listOfStrings) || listOfStrings.size() == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Iterator<String> iter = listOfStrings.iterator();
|
||||
String current, previous = iter.next();
|
||||
while (iter.hasNext()) {
|
||||
current = iter.next();
|
||||
if (previous.compareTo(current) > 0) {
|
||||
return false;
|
||||
}
|
||||
previous = current;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean checkIfSortedUsingIterativeApproach(List<Employee> employees, Comparator<Employee> employeeComparator) {
|
||||
if (isEmpty(employees) || employees.size() == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Iterator<Employee> iter = employees.iterator();
|
||||
Employee current, previous = iter.next();
|
||||
while (iter.hasNext()) {
|
||||
current = iter.next();
|
||||
if (employeeComparator.compare(previous, current) > 0) {
|
||||
return false;
|
||||
}
|
||||
previous = current;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean checkIfSortedUsingRecursion(List<String> listOfStrings) {
|
||||
return isSortedRecursive(listOfStrings, listOfStrings.size());
|
||||
}
|
||||
|
||||
public static boolean isSortedRecursive(List<String> listOfStrings, int index) {
|
||||
if (index < 2) {
|
||||
return true;
|
||||
} else if (listOfStrings.get(index - 2)
|
||||
.compareTo(listOfStrings.get(index - 1)) > 0) {
|
||||
return false;
|
||||
} else {
|
||||
return isSortedRecursive(listOfStrings, index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean checkIfSortedUsingOrderingClass(List<String> listOfStrings) {
|
||||
return Ordering.<String> natural()
|
||||
.isOrdered(listOfStrings);
|
||||
}
|
||||
|
||||
public static boolean checkIfSortedUsingOrderingClass(List<Employee> employees, Comparator<Employee> employeeComparator) {
|
||||
return Ordering.from(employeeComparator)
|
||||
.isOrdered(employees);
|
||||
}
|
||||
|
||||
public static boolean checkIfSortedUsingOrderingClassHandlingNull(List<String> listOfStrings) {
|
||||
return Ordering.<String> natural()
|
||||
.nullsLast()
|
||||
.isOrdered(listOfStrings);
|
||||
}
|
||||
|
||||
public static boolean checkIfSortedUsingComparators(List<String> listOfStrings) {
|
||||
return Comparators.isInOrder(listOfStrings, Comparator.<String> naturalOrder());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.baeldung.algorithms.enumstatemachine;
|
||||
|
||||
public enum LeaveRequestState {
|
||||
|
||||
Submitted {
|
||||
@Override
|
||||
public LeaveRequestState nextState() {
|
||||
System.out.println("Starting the Leave Request and sending to Team Leader for approval.");
|
||||
return Escalated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String responsiblePerson() {
|
||||
return "Employee";
|
||||
}
|
||||
},
|
||||
Escalated {
|
||||
@Override
|
||||
public LeaveRequestState nextState() {
|
||||
System.out.println("Reviewing the Leave Request and escalating to Department Manager.");
|
||||
return Approved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String responsiblePerson() {
|
||||
return "Team Leader";
|
||||
}
|
||||
},
|
||||
Approved {
|
||||
@Override
|
||||
public LeaveRequestState nextState() {
|
||||
System.out.println("Approving the Leave Request.");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String responsiblePerson() {
|
||||
return "Department Manager";
|
||||
}
|
||||
};
|
||||
|
||||
public abstract String responsiblePerson();
|
||||
|
||||
public abstract LeaveRequestState nextState();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.baeldung.algorithms.graphcycledetection.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Graph {
|
||||
|
||||
private List<Vertex> vertices;
|
||||
|
||||
public Graph() {
|
||||
this.vertices = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Graph(List<Vertex> vertices) {
|
||||
this.vertices = vertices;
|
||||
}
|
||||
|
||||
public void addVertex(Vertex vertex) {
|
||||
this.vertices.add(vertex);
|
||||
}
|
||||
|
||||
public void addEdge(Vertex from, Vertex to) {
|
||||
from.addNeighbour(to);
|
||||
}
|
||||
|
||||
public boolean hasCycle() {
|
||||
for (Vertex vertex : vertices) {
|
||||
if (!vertex.isVisited() && hasCycle(vertex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasCycle(Vertex sourceVertex) {
|
||||
sourceVertex.setBeingVisited(true);
|
||||
|
||||
for (Vertex neighbour : sourceVertex.getAdjacencyList()) {
|
||||
if (neighbour.isBeingVisited()) {
|
||||
// backward edge exists
|
||||
return true;
|
||||
} else if (!neighbour.isVisited() && hasCycle(neighbour)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
sourceVertex.setBeingVisited(false);
|
||||
sourceVertex.setVisited(true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.baeldung.algorithms.graphcycledetection.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Vertex {
|
||||
|
||||
private String label;
|
||||
|
||||
private boolean visited;
|
||||
|
||||
private boolean beingVisited;
|
||||
|
||||
private List<Vertex> adjacencyList;
|
||||
|
||||
public Vertex(String label) {
|
||||
this.label = label;
|
||||
this.adjacencyList = new ArrayList<>();
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public boolean isVisited() {
|
||||
return visited;
|
||||
}
|
||||
|
||||
public void setVisited(boolean visited) {
|
||||
this.visited = visited;
|
||||
}
|
||||
|
||||
public boolean isBeingVisited() {
|
||||
return beingVisited;
|
||||
}
|
||||
|
||||
public void setBeingVisited(boolean beingVisited) {
|
||||
this.beingVisited = beingVisited;
|
||||
}
|
||||
|
||||
public List<Vertex> getAdjacencyList() {
|
||||
return adjacencyList;
|
||||
}
|
||||
|
||||
public void setAdjacencyList(List<Vertex> adjacencyList) {
|
||||
this.adjacencyList = adjacencyList;
|
||||
}
|
||||
|
||||
public void addNeighbour(Vertex adjacent) {
|
||||
this.adjacencyList.add(adjacent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.baeldung.algorithms.kmeans;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Encapsulates all coordinates for a particular cluster centroid.
|
||||
*/
|
||||
public class Centroid {
|
||||
|
||||
/**
|
||||
* The centroid coordinates.
|
||||
*/
|
||||
private final Map<String, Double> coordinates;
|
||||
|
||||
public Centroid(Map<String, Double> coordinates) {
|
||||
this.coordinates = coordinates;
|
||||
}
|
||||
|
||||
public Map<String, Double> getCoordinates() {
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Centroid centroid = (Centroid) o;
|
||||
return Objects.equals(getCoordinates(), centroid.getCoordinates());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getCoordinates());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Centroid " + coordinates;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.algorithms.kmeans;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Defines a contract to calculate distance between two feature vectors. The less the
|
||||
* calculated distance, the more two items are similar to each other.
|
||||
*/
|
||||
public interface Distance {
|
||||
|
||||
/**
|
||||
* Calculates the distance between two feature vectors.
|
||||
*
|
||||
* @param f1 The first set of features.
|
||||
* @param f2 The second set of features.
|
||||
* @return Calculated distance.
|
||||
* @throws IllegalArgumentException If the given feature vectors are invalid.
|
||||
*/
|
||||
double calculate(Map<String, Double> f1, Map<String, Double> f2);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.algorithms.kmeans;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Encapsulates methods to calculates errors between centroid and the cluster members.
|
||||
*/
|
||||
public class Errors {
|
||||
|
||||
public static double sse(Map<Centroid, List<Record>> clustered, Distance distance) {
|
||||
double sum = 0;
|
||||
for (Map.Entry<Centroid, List<Record>> entry : clustered.entrySet()) {
|
||||
Centroid centroid = entry.getKey();
|
||||
for (Record record : entry.getValue()) {
|
||||
double d = distance.calculate(centroid.getCoordinates(), record.getFeatures());
|
||||
sum += Math.pow(d, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.algorithms.kmeans;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Calculates the distance between two items using the Euclidean formula.
|
||||
*/
|
||||
public class EuclideanDistance implements Distance {
|
||||
|
||||
@Override
|
||||
public double calculate(Map<String, Double> f1, Map<String, Double> f2) {
|
||||
if (f1 == null || f2 == null) {
|
||||
throw new IllegalArgumentException("Feature vectors can't be null");
|
||||
}
|
||||
|
||||
double sum = 0;
|
||||
for (String key : f1.keySet()) {
|
||||
Double v1 = f1.get(key);
|
||||
Double v2 = f2.get(key);
|
||||
|
||||
if (v1 != null && v2 != null) sum += Math.pow(v1 - v2, 2);
|
||||
}
|
||||
|
||||
return Math.sqrt(sum);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package com.baeldung.algorithms.kmeans;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
/**
|
||||
* Encapsulates an implementation of KMeans clustering algorithm.
|
||||
*
|
||||
* @author Ali Dehghani
|
||||
*/
|
||||
public class KMeans {
|
||||
|
||||
private KMeans() {
|
||||
throw new IllegalAccessError("You shouldn't call this constructor");
|
||||
}
|
||||
|
||||
/**
|
||||
* Will be used to generate random numbers.
|
||||
*/
|
||||
private static final Random random = new Random();
|
||||
|
||||
/**
|
||||
* Performs the K-Means clustering algorithm on the given dataset.
|
||||
*
|
||||
* @param records The dataset.
|
||||
* @param k Number of Clusters.
|
||||
* @param distance To calculate the distance between two items.
|
||||
* @param maxIterations Upper bound for the number of iterations.
|
||||
* @return K clusters along with their features.
|
||||
*/
|
||||
public static Map<Centroid, List<Record>> fit(List<Record> records, int k, Distance distance, int maxIterations) {
|
||||
applyPreconditions(records, k, distance, maxIterations);
|
||||
|
||||
List<Centroid> centroids = randomCentroids(records, k);
|
||||
Map<Centroid, List<Record>> clusters = new HashMap<>();
|
||||
Map<Centroid, List<Record>> lastState = new HashMap<>();
|
||||
|
||||
// iterate for a pre-defined number of times
|
||||
for (int i = 0; i < maxIterations; i++) {
|
||||
boolean isLastIteration = i == maxIterations - 1;
|
||||
|
||||
// in each iteration we should find the nearest centroid for each record
|
||||
for (Record record : records) {
|
||||
Centroid centroid = nearestCentroid(record, centroids, distance);
|
||||
assignToCluster(clusters, record, centroid);
|
||||
}
|
||||
|
||||
// if the assignment does not change, then the algorithm terminates
|
||||
boolean shouldTerminate = isLastIteration || clusters.equals(lastState);
|
||||
lastState = clusters;
|
||||
if (shouldTerminate) {
|
||||
break;
|
||||
}
|
||||
|
||||
// at the end of each iteration we should relocate the centroids
|
||||
centroids = relocateCentroids(clusters);
|
||||
clusters = new HashMap<>();
|
||||
}
|
||||
|
||||
return lastState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move all cluster centroids to the average of all assigned features.
|
||||
*
|
||||
* @param clusters The current cluster configuration.
|
||||
* @return Collection of new and relocated centroids.
|
||||
*/
|
||||
private static List<Centroid> relocateCentroids(Map<Centroid, List<Record>> clusters) {
|
||||
return clusters
|
||||
.entrySet()
|
||||
.stream()
|
||||
.map(e -> average(e.getKey(), e.getValue()))
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the given centroid to the average position of all assigned features. If
|
||||
* the centroid has no feature in its cluster, then there would be no need for a
|
||||
* relocation. Otherwise, for each entry we calculate the average of all records
|
||||
* first by summing all the entries and then dividing the final summation value by
|
||||
* the number of records.
|
||||
*
|
||||
* @param centroid The centroid to move.
|
||||
* @param records The assigned features.
|
||||
* @return The moved centroid.
|
||||
*/
|
||||
private static Centroid average(Centroid centroid, List<Record> records) {
|
||||
// if this cluster is empty, then we shouldn't move the centroid
|
||||
if (records == null || records.isEmpty()) {
|
||||
return centroid;
|
||||
}
|
||||
|
||||
// Since some records don't have all possible attributes, we initialize
|
||||
// average coordinates equal to current centroid coordinates
|
||||
Map<String, Double> average = centroid.getCoordinates();
|
||||
|
||||
// The average function works correctly if we clear all coordinates corresponding
|
||||
// to present record attributes
|
||||
records
|
||||
.stream()
|
||||
.flatMap(e -> e
|
||||
.getFeatures()
|
||||
.keySet()
|
||||
.stream())
|
||||
.forEach(k -> average.put(k, 0.0));
|
||||
|
||||
for (Record record : records) {
|
||||
record
|
||||
.getFeatures()
|
||||
.forEach((k, v) -> average.compute(k, (k1, currentValue) -> v + currentValue));
|
||||
}
|
||||
|
||||
average.forEach((k, v) -> average.put(k, v / records.size()));
|
||||
|
||||
return new Centroid(average);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a feature vector to the given centroid. If this is the first assignment for this centroid,
|
||||
* first we should create the list.
|
||||
*
|
||||
* @param clusters The current cluster configuration.
|
||||
* @param record The feature vector.
|
||||
* @param centroid The centroid.
|
||||
*/
|
||||
private static void assignToCluster(Map<Centroid, List<Record>> clusters, Record record, Centroid centroid) {
|
||||
clusters.compute(centroid, (key, list) -> {
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
|
||||
list.add(record);
|
||||
return list;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* With the help of the given distance calculator, iterates through centroids and finds the
|
||||
* nearest one to the given record.
|
||||
*
|
||||
* @param record The feature vector to find a centroid for.
|
||||
* @param centroids Collection of all centroids.
|
||||
* @param distance To calculate the distance between two items.
|
||||
* @return The nearest centroid to the given feature vector.
|
||||
*/
|
||||
private static Centroid nearestCentroid(Record record, List<Centroid> centroids, Distance distance) {
|
||||
double minimumDistance = Double.MAX_VALUE;
|
||||
Centroid nearest = null;
|
||||
|
||||
for (Centroid centroid : centroids) {
|
||||
double currentDistance = distance.calculate(record.getFeatures(), centroid.getCoordinates());
|
||||
|
||||
if (currentDistance < minimumDistance) {
|
||||
minimumDistance = currentDistance;
|
||||
nearest = centroid;
|
||||
}
|
||||
}
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates k random centroids. Before kicking-off the centroid generation process,
|
||||
* first we calculate the possible value range for each attribute. Then when
|
||||
* we're going to generate the centroids, we generate random coordinates in
|
||||
* the [min, max] range for each attribute.
|
||||
*
|
||||
* @param records The dataset which helps to calculate the [min, max] range for
|
||||
* each attribute.
|
||||
* @param k Number of clusters.
|
||||
* @return Collections of randomly generated centroids.
|
||||
*/
|
||||
private static List<Centroid> randomCentroids(List<Record> records, int k) {
|
||||
List<Centroid> centroids = new ArrayList<>();
|
||||
Map<String, Double> maxs = new HashMap<>();
|
||||
Map<String, Double> mins = new HashMap<>();
|
||||
|
||||
for (Record record : records) {
|
||||
record
|
||||
.getFeatures()
|
||||
.forEach((key, value) -> {
|
||||
// compares the value with the current max and choose the bigger value between them
|
||||
maxs.compute(key, (k1, max) -> max == null || value > max ? value : max);
|
||||
|
||||
// compare the value with the current min and choose the smaller value between them
|
||||
mins.compute(key, (k1, min) -> min == null || value < min ? value : min);
|
||||
});
|
||||
}
|
||||
|
||||
Set<String> attributes = records
|
||||
.stream()
|
||||
.flatMap(e -> e
|
||||
.getFeatures()
|
||||
.keySet()
|
||||
.stream())
|
||||
.collect(toSet());
|
||||
for (int i = 0; i < k; i++) {
|
||||
Map<String, Double> coordinates = new HashMap<>();
|
||||
for (String attribute : attributes) {
|
||||
double max = maxs.get(attribute);
|
||||
double min = mins.get(attribute);
|
||||
coordinates.put(attribute, random.nextDouble() * (max - min) + min);
|
||||
}
|
||||
|
||||
centroids.add(new Centroid(coordinates));
|
||||
}
|
||||
|
||||
return centroids;
|
||||
}
|
||||
|
||||
private static void applyPreconditions(List<Record> records, int k, Distance distance, int maxIterations) {
|
||||
if (records == null || records.isEmpty()) {
|
||||
throw new IllegalArgumentException("The dataset can't be empty");
|
||||
}
|
||||
|
||||
if (k <= 1) {
|
||||
throw new IllegalArgumentException("It doesn't make sense to have less than or equal to 1 cluster");
|
||||
}
|
||||
|
||||
if (distance == null) {
|
||||
throw new IllegalArgumentException("The distance calculator is required");
|
||||
}
|
||||
|
||||
if (maxIterations <= 0) {
|
||||
throw new IllegalArgumentException("Max iterations should be a positive number");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.baeldung.algorithms.kmeans;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import okhttp3.OkHttpClient;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.jackson.JacksonConverterFactory;
|
||||
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
public class LastFm {
|
||||
|
||||
private static OkHttpClient okHttp = new OkHttpClient.Builder()
|
||||
.addInterceptor(new LastFmService.Authenticator("put your API key here"))
|
||||
.build();
|
||||
|
||||
private static Retrofit retrofit = new Retrofit.Builder()
|
||||
.client(okHttp)
|
||||
.addConverterFactory(JacksonConverterFactory.create())
|
||||
.baseUrl("http://ws.audioscrobbler.com/")
|
||||
.build();
|
||||
|
||||
private static LastFmService lastFm = retrofit.create(LastFmService.class);
|
||||
|
||||
private static ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
List<String> artists = getTop100Artists();
|
||||
Set<String> tags = getTop100Tags();
|
||||
List<Record> records = datasetWithTaggedArtists(artists, tags);
|
||||
|
||||
Map<Centroid, List<Record>> clusters = KMeans.fit(records, 7, new EuclideanDistance(), 1000);
|
||||
// Print the cluster configuration
|
||||
clusters.forEach((key, value) -> {
|
||||
System.out.println("------------------------------ CLUSTER -----------------------------------");
|
||||
|
||||
System.out.println(sortedCentroid(key));
|
||||
String members = String.join(", ", value
|
||||
.stream()
|
||||
.map(Record::getDescription)
|
||||
.collect(toSet()));
|
||||
System.out.print(members);
|
||||
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
});
|
||||
|
||||
Map<String, Object> json = convertToD3CompatibleMap(clusters);
|
||||
System.out.println(mapper.writeValueAsString(json));
|
||||
}
|
||||
|
||||
private static Map<String, Object> convertToD3CompatibleMap(Map<Centroid, List<Record>> clusters) {
|
||||
Map<String, Object> json = new HashMap<>();
|
||||
json.put("name", "Musicians");
|
||||
List<Map<String, Object>> children = new ArrayList<>();
|
||||
clusters.forEach((key, value) -> {
|
||||
Map<String, Object> child = new HashMap<>();
|
||||
child.put("name", dominantGenre(sortedCentroid(key)));
|
||||
List<Map<String, String>> nested = new ArrayList<>();
|
||||
for (Record record : value) {
|
||||
nested.add(Collections.singletonMap("name", record.getDescription()));
|
||||
}
|
||||
child.put("children", nested);
|
||||
|
||||
children.add(child);
|
||||
});
|
||||
json.put("children", children);
|
||||
return json;
|
||||
}
|
||||
|
||||
private static String dominantGenre(Centroid centroid) {
|
||||
return centroid
|
||||
.getCoordinates()
|
||||
.keySet()
|
||||
.stream()
|
||||
.limit(2)
|
||||
.collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
private static Centroid sortedCentroid(Centroid key) {
|
||||
List<Map.Entry<String, Double>> entries = new ArrayList<>(key
|
||||
.getCoordinates()
|
||||
.entrySet());
|
||||
entries.sort((e1, e2) -> e2
|
||||
.getValue()
|
||||
.compareTo(e1.getValue()));
|
||||
|
||||
Map<String, Double> sorted = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Double> entry : entries) {
|
||||
sorted.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return new Centroid(sorted);
|
||||
}
|
||||
|
||||
private static List<Record> datasetWithTaggedArtists(List<String> artists, Set<String> topTags) throws IOException {
|
||||
List<Record> records = new ArrayList<>();
|
||||
for (String artist : artists) {
|
||||
Map<String, Double> tags = lastFm
|
||||
.topTagsFor(artist)
|
||||
.execute()
|
||||
.body()
|
||||
.all();
|
||||
|
||||
// Only keep popular tags.
|
||||
tags
|
||||
.entrySet()
|
||||
.removeIf(e -> !topTags.contains(e.getKey()));
|
||||
|
||||
records.add(new Record(artist, tags));
|
||||
}
|
||||
return records;
|
||||
}
|
||||
|
||||
private static Set<String> getTop100Tags() throws IOException {
|
||||
return lastFm
|
||||
.topTags()
|
||||
.execute()
|
||||
.body()
|
||||
.all();
|
||||
}
|
||||
|
||||
private static List<String> getTop100Artists() throws IOException {
|
||||
List<String> artists = new ArrayList<>();
|
||||
for (int i = 1; i <= 2; i++) {
|
||||
artists.addAll(lastFm
|
||||
.topArtists(i)
|
||||
.execute()
|
||||
.body()
|
||||
.all());
|
||||
}
|
||||
|
||||
return artists;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.baeldung.algorithms.kmeans;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public interface LastFmService {
|
||||
|
||||
@GET("/2.0/?method=chart.gettopartists&format=json&limit=50")
|
||||
Call<Artists> topArtists(@Query("page") int page);
|
||||
|
||||
@GET("/2.0/?method=artist.gettoptags&format=json&limit=20&autocorrect=1")
|
||||
Call<Tags> topTagsFor(@Query("artist") String artist);
|
||||
|
||||
@GET("/2.0/?method=chart.gettoptags&format=json&limit=100")
|
||||
Call<TopTags> topTags();
|
||||
|
||||
/**
|
||||
* HTTP interceptor to intercept all HTTP requests and add the API key to them.
|
||||
*/
|
||||
class Authenticator implements Interceptor {
|
||||
|
||||
private final String apiKey;
|
||||
|
||||
Authenticator(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
HttpUrl url = chain
|
||||
.request()
|
||||
.url()
|
||||
.newBuilder()
|
||||
.addQueryParameter("api_key", apiKey)
|
||||
.build();
|
||||
Request request = chain
|
||||
.request()
|
||||
.newBuilder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
return chain.proceed(request);
|
||||
}
|
||||
}
|
||||
|
||||
@JsonAutoDetect(fieldVisibility = ANY)
|
||||
class TopTags {
|
||||
|
||||
private Map<String, Object> tags;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<String> all() {
|
||||
List<Map<String, Object>> topTags = (List<Map<String, Object>>) tags.get("tag");
|
||||
return topTags
|
||||
.stream()
|
||||
.map(e -> ((String) e.get("name")))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
@JsonAutoDetect(fieldVisibility = ANY)
|
||||
class Tags {
|
||||
|
||||
@JsonProperty("toptags") private Map<String, Object> topTags;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Double> all() {
|
||||
try {
|
||||
Map<String, Double> all = new HashMap<>();
|
||||
List<Map<String, Object>> tags = (List<Map<String, Object>>) topTags.get("tag");
|
||||
for (Map<String, Object> tag : tags) {
|
||||
all.put(((String) tag.get("name")), ((Integer) tag.get("count")).doubleValue());
|
||||
}
|
||||
|
||||
return all;
|
||||
} catch (Exception e) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JsonAutoDetect(fieldVisibility = ANY)
|
||||
class Artists {
|
||||
|
||||
private Map<String, Object> artists;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<String> all() {
|
||||
try {
|
||||
List<Map<String, Object>> artists = (List<Map<String, Object>>) this.artists.get("artist");
|
||||
return artists
|
||||
.stream()
|
||||
.map(e -> ((String) e.get("name")))
|
||||
.collect(toList());
|
||||
} catch (Exception e) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.baeldung.algorithms.kmeans;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Encapsulates all feature values for a few attributes. Optionally each record
|
||||
* can be described with the {@link #description} field.
|
||||
*/
|
||||
public class Record {
|
||||
|
||||
/**
|
||||
* The record description. For example, this can be the artist name for the famous musician
|
||||
* example.
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* Encapsulates all attributes and their corresponding values, i.e. features.
|
||||
*/
|
||||
private final Map<String, Double> features;
|
||||
|
||||
public Record(String description, Map<String, Double> features) {
|
||||
this.description = description;
|
||||
this.features = features;
|
||||
}
|
||||
|
||||
public Record(Map<String, Double> features) {
|
||||
this("", features);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Map<String, Double> getFeatures() {
|
||||
return features;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String prefix = description == null || description
|
||||
.trim()
|
||||
.isEmpty() ? "Record" : description;
|
||||
|
||||
return prefix + ": " + features;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Record record = (Record) o;
|
||||
return Objects.equals(getDescription(), record.getDescription()) && Objects.equals(getFeatures(), record.getFeatures());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getDescription(), getFeatures());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.baeldung.algorithms.printtriangles;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class PrintTriangleExamples {
|
||||
|
||||
public static String printARightTriangle(int N) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int r = 1; r <= N; r++) {
|
||||
for (int j = 1; j <= r; j++) {
|
||||
result.append("*");
|
||||
}
|
||||
result.append(System.lineSeparator());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String printAnIsoscelesTriangle(int N) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int r = 1; r <= N; r++) {
|
||||
for (int sp = 1; sp <= N - r; sp++) {
|
||||
result.append(" ");
|
||||
}
|
||||
for (int c = 1; c <= (r * 2) - 1; c++) {
|
||||
result.append("*");
|
||||
}
|
||||
result.append(System.lineSeparator());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String printAnIsoscelesTriangleUsingStringUtils(int N) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int r = 1; r <= N; r++) {
|
||||
result.append(StringUtils.repeat(' ', N - r));
|
||||
result.append(StringUtils.repeat('*', 2 * r - 1));
|
||||
result.append(System.lineSeparator());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String printAnIsoscelesTriangleUsingSubstring(int N) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
String helperString = StringUtils.repeat(' ', N - 1) + StringUtils.repeat('*', N * 2 - 1);
|
||||
|
||||
for (int r = 0; r < N; r++) {
|
||||
result.append(helperString.substring(r, N + 2 * r));
|
||||
result.append(System.lineSeparator());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(printARightTriangle(5));
|
||||
System.out.println(printAnIsoscelesTriangle(5));
|
||||
System.out.println(printAnIsoscelesTriangleUsingStringUtils(5));
|
||||
System.out.println(printAnIsoscelesTriangleUsingSubstring(5));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.baeldung.algorithms.romannumerals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class RomanArabicConverter {
|
||||
|
||||
public static int romanToArabic(String input) {
|
||||
String romanNumeral = input.toUpperCase();
|
||||
int result = 0;
|
||||
|
||||
List<RomanNumeral> romanNumerals = RomanNumeral.getReverseSortedValues();
|
||||
|
||||
int i = 0;
|
||||
|
||||
while ((romanNumeral.length() > 0) && (i < romanNumerals.size())) {
|
||||
RomanNumeral symbol = romanNumerals.get(i);
|
||||
if (romanNumeral.startsWith(symbol.name())) {
|
||||
result += symbol.getValue();
|
||||
romanNumeral = romanNumeral.substring(symbol.name().length());
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (romanNumeral.length() > 0) {
|
||||
throw new IllegalArgumentException(input + " cannot be converted to a Roman Numeral");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String arabicToRoman(int number) {
|
||||
if ((number <= 0) || (number > 4000)) {
|
||||
throw new IllegalArgumentException(number + " is not in range (0,4000]");
|
||||
}
|
||||
|
||||
List<RomanNumeral> romanNumerals = RomanNumeral.getReverseSortedValues();
|
||||
|
||||
int i = 0;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
while (number > 0 && i < romanNumerals.size()) {
|
||||
RomanNumeral currentSymbol = romanNumerals.get(i);
|
||||
if (currentSymbol.getValue() <= number) {
|
||||
sb.append(currentSymbol.name());
|
||||
number -= currentSymbol.getValue();
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.algorithms.romannumerals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
enum RomanNumeral {
|
||||
I(1), IV(4), V(5), IX(9), X(10), XL(40), L(50), XC(90), C(100), CD(400), D(500), CM(900), M(1000);
|
||||
|
||||
private int value;
|
||||
|
||||
RomanNumeral(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static List<RomanNumeral> getReverseSortedValues() {
|
||||
return Arrays.stream(values())
|
||||
.sorted(Comparator.comparing((RomanNumeral e) -> e.value).reversed())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.algorithms.twopointertechnique;
|
||||
|
||||
public class LinkedListFindMiddle {
|
||||
|
||||
public <T> T findMiddle(MyNode<T> head) {
|
||||
MyNode<T> slowPointer = head;
|
||||
MyNode<T> fastPointer = head;
|
||||
|
||||
while (fastPointer.next != null && fastPointer.next.next != null) {
|
||||
fastPointer = fastPointer.next.next;
|
||||
slowPointer = slowPointer.next;
|
||||
}
|
||||
return slowPointer.data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.algorithms.twopointertechnique;
|
||||
|
||||
public class MyNode<E> {
|
||||
MyNode<E> next;
|
||||
E data;
|
||||
|
||||
public MyNode(E value) {
|
||||
data = value;
|
||||
next = null;
|
||||
}
|
||||
|
||||
public MyNode(E value, MyNode<E> n) {
|
||||
data = value;
|
||||
next = n;
|
||||
}
|
||||
|
||||
public void setNext(MyNode<E> n) {
|
||||
next = n;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.baeldung.algorithms.twopointertechnique;
|
||||
|
||||
public class RotateArray {
|
||||
|
||||
public void rotate(int[] input, int step) {
|
||||
step %= input.length;
|
||||
reverse(input, 0, input.length - 1);
|
||||
reverse(input, 0, step - 1);
|
||||
reverse(input, step, input.length - 1);
|
||||
}
|
||||
|
||||
private void reverse(int[] input, int start, int end) {
|
||||
while (start < end) {
|
||||
int temp = input[start];
|
||||
input[start] = input[end];
|
||||
input[end] = temp;
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.algorithms.twopointertechnique;
|
||||
|
||||
public class TwoSum {
|
||||
|
||||
public boolean twoSum(int[] input, int targetValue) {
|
||||
|
||||
int pointerOne = 0;
|
||||
int pointerTwo = input.length - 1;
|
||||
|
||||
while (pointerOne < pointerTwo) {
|
||||
int sum = input[pointerOne] + input[pointerTwo];
|
||||
|
||||
if (sum == targetValue) {
|
||||
return true;
|
||||
} else if (sum < targetValue) {
|
||||
pointerOne++;
|
||||
} else {
|
||||
pointerTwo--;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean twoSumSlow(int[] input, int targetValue) {
|
||||
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
for (int j = 1; j < input.length; j++) {
|
||||
if (input[i] + input[j] == targetValue) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.baeldung.folding;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* Calculate a hash value for the strings using the folding technique.
|
||||
*
|
||||
* The implementation serves only to the illustration purposes and is far
|
||||
* from being the most efficient.
|
||||
*
|
||||
* @author A.Shcherbakov
|
||||
*
|
||||
*/
|
||||
public class FoldingHash {
|
||||
|
||||
/**
|
||||
* Calculate the hash value of a given string.
|
||||
*
|
||||
* @param str Assume it is not null
|
||||
* @param groupSize the group size in the folding technique
|
||||
* @param maxValue defines a max value that the hash may acquire (exclusive)
|
||||
* @return integer value from 0 (inclusive) to maxValue (exclusive)
|
||||
*/
|
||||
public int hash(String str, int groupSize, int maxValue) {
|
||||
final int[] codes = this.toAsciiCodes(str);
|
||||
return IntStream.range(0, str.length())
|
||||
.filter(i -> i % groupSize == 0)
|
||||
.mapToObj(i -> extract(codes, i, groupSize))
|
||||
.map(block -> concatenate(block))
|
||||
.reduce(0, (a, b) -> (a + b) % maxValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new array of given length whose elements are take from
|
||||
* the original one starting from the offset.
|
||||
*
|
||||
* If the original array has not enough elements, the returning array will contain
|
||||
* element from the offset till the end of the original array.
|
||||
*
|
||||
* @param numbers original array. Assume it is not null.
|
||||
* @param offset index of the element to start from. Assume it is less than the size of the array
|
||||
* @param length max size of the resulting array
|
||||
* @return
|
||||
*/
|
||||
public int[] extract(int[] numbers, int offset, int length) {
|
||||
final int defect = numbers.length - (offset + length);
|
||||
final int s = defect < 0 ? length + defect : length;
|
||||
int[] result = new int[s];
|
||||
for (int index = 0; index < s; index++) {
|
||||
result[index] = numbers[index + offset];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate the numbers into a single number as if they were strings.
|
||||
* Assume that the procedure does not suffer from the overflow.
|
||||
* @param numbers integers to concatenate
|
||||
* @return
|
||||
*/
|
||||
public int concatenate(int[] numbers) {
|
||||
final String merged = IntStream.of(numbers)
|
||||
.mapToObj(number -> "" + number)
|
||||
.collect(Collectors.joining());
|
||||
return Integer.parseInt(merged, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the string into its characters' ASCII codes.
|
||||
* @param str input string
|
||||
* @return
|
||||
*/
|
||||
private int[] toAsciiCodes(String str) {
|
||||
return str.chars()
|
||||
.toArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.folding;
|
||||
|
||||
/**
|
||||
* Code snippet for article "A Guide to the Folding Technique".
|
||||
*
|
||||
* @author A.Shcherbakov
|
||||
*
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
public static void main(String... arg) {
|
||||
FoldingHash hasher = new FoldingHash();
|
||||
final String str = "Java language";
|
||||
System.out.println(hasher.hash(str, 2, 100_000));
|
||||
System.out.println(hasher.hash(str, 3, 1_000));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,490 @@
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"name": "Radiohead"
|
||||
},
|
||||
{
|
||||
"name": "Red Hot Chili Peppers"
|
||||
},
|
||||
{
|
||||
"name": "Coldplay"
|
||||
},
|
||||
{
|
||||
"name": "Nirvana"
|
||||
},
|
||||
{
|
||||
"name": "Panic! at the Disco"
|
||||
},
|
||||
{
|
||||
"name": "The Cure"
|
||||
},
|
||||
{
|
||||
"name": "Linkin Park"
|
||||
},
|
||||
{
|
||||
"name": "Radiohead"
|
||||
},
|
||||
{
|
||||
"name": "Red Hot Chili Peppers"
|
||||
},
|
||||
{
|
||||
"name": "Coldplay"
|
||||
},
|
||||
{
|
||||
"name": "Nirvana"
|
||||
},
|
||||
{
|
||||
"name": "Panic! at the Disco"
|
||||
},
|
||||
{
|
||||
"name": "The Cure"
|
||||
},
|
||||
{
|
||||
"name": "Linkin Park"
|
||||
},
|
||||
{
|
||||
"name": "Muse"
|
||||
},
|
||||
{
|
||||
"name": "Maroon 5"
|
||||
},
|
||||
{
|
||||
"name": "Foo Fighters"
|
||||
},
|
||||
{
|
||||
"name": "Paramore"
|
||||
},
|
||||
{
|
||||
"name": "Oasis"
|
||||
},
|
||||
{
|
||||
"name": "Fall Out Boy"
|
||||
},
|
||||
{
|
||||
"name": "OneRepublic"
|
||||
},
|
||||
{
|
||||
"name": "Weezer"
|
||||
},
|
||||
{
|
||||
"name": "System of a Down"
|
||||
},
|
||||
{
|
||||
"name": "The White Stripes"
|
||||
}
|
||||
],
|
||||
"name": "rock, alternative"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"name": "Lil Nas X"
|
||||
},
|
||||
{
|
||||
"name": "Post Malone"
|
||||
},
|
||||
{
|
||||
"name": "Drake"
|
||||
},
|
||||
{
|
||||
"name": "Kanye West"
|
||||
},
|
||||
{
|
||||
"name": "Kendrick Lamar"
|
||||
},
|
||||
{
|
||||
"name": "Tyler, the Creator"
|
||||
},
|
||||
{
|
||||
"name": "Eminem"
|
||||
},
|
||||
{
|
||||
"name": "Childish Gambino"
|
||||
},
|
||||
{
|
||||
"name": "Frank Ocean"
|
||||
},
|
||||
{
|
||||
"name": "Lil Nas X"
|
||||
},
|
||||
{
|
||||
"name": "Post Malone"
|
||||
},
|
||||
{
|
||||
"name": "Drake"
|
||||
},
|
||||
{
|
||||
"name": "Kanye West"
|
||||
},
|
||||
{
|
||||
"name": "Kendrick Lamar"
|
||||
},
|
||||
{
|
||||
"name": "Tyler, the Creator"
|
||||
},
|
||||
{
|
||||
"name": "Eminem"
|
||||
},
|
||||
{
|
||||
"name": "Childish Gambino"
|
||||
},
|
||||
{
|
||||
"name": "Frank Ocean"
|
||||
},
|
||||
{
|
||||
"name": "Lizzo"
|
||||
},
|
||||
{
|
||||
"name": "Travi$ Scott"
|
||||
},
|
||||
{
|
||||
"name": "A$AP Rocky"
|
||||
},
|
||||
{
|
||||
"name": "Nicki Minaj"
|
||||
},
|
||||
{
|
||||
"name": "xxxtentacion"
|
||||
}
|
||||
],
|
||||
"name": "Hip-Hop, rap"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"name": "Arctic Monkeys"
|
||||
},
|
||||
{
|
||||
"name": "Imagine Dragons"
|
||||
},
|
||||
{
|
||||
"name": "The Killers"
|
||||
},
|
||||
{
|
||||
"name": "Gorillaz"
|
||||
},
|
||||
{
|
||||
"name": "The Black Keys"
|
||||
},
|
||||
{
|
||||
"name": "Arctic Monkeys"
|
||||
},
|
||||
{
|
||||
"name": "Imagine Dragons"
|
||||
},
|
||||
{
|
||||
"name": "The Killers"
|
||||
},
|
||||
{
|
||||
"name": "Gorillaz"
|
||||
},
|
||||
{
|
||||
"name": "The Black Keys"
|
||||
},
|
||||
{
|
||||
"name": "Twenty One Pilots"
|
||||
},
|
||||
{
|
||||
"name": "Ellie Goulding"
|
||||
},
|
||||
{
|
||||
"name": "Florence + the Machine"
|
||||
},
|
||||
{
|
||||
"name": "Vampire Weekend"
|
||||
},
|
||||
{
|
||||
"name": "The Smiths"
|
||||
},
|
||||
{
|
||||
"name": "The Strokes"
|
||||
},
|
||||
{
|
||||
"name": "MGMT"
|
||||
},
|
||||
{
|
||||
"name": "Foster the People"
|
||||
},
|
||||
{
|
||||
"name": "Two Door Cinema Club"
|
||||
},
|
||||
{
|
||||
"name": "Cage the Elephant"
|
||||
},
|
||||
{
|
||||
"name": "Arcade Fire"
|
||||
},
|
||||
{
|
||||
"name": "The 1975"
|
||||
}
|
||||
],
|
||||
"name": "indie, alternative"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"name": "Ed Sheeran"
|
||||
},
|
||||
{
|
||||
"name": "Tame Impala"
|
||||
},
|
||||
{
|
||||
"name": "Ed Sheeran"
|
||||
},
|
||||
{
|
||||
"name": "Tame Impala"
|
||||
},
|
||||
{
|
||||
"name": "Green Day"
|
||||
},
|
||||
{
|
||||
"name": "Metallica"
|
||||
},
|
||||
{
|
||||
"name": "blink-182"
|
||||
},
|
||||
{
|
||||
"name": "Bon Iver"
|
||||
},
|
||||
{
|
||||
"name": "The Clash"
|
||||
}
|
||||
],
|
||||
"name": "rock, punk rock"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"name": "Calvin Harris"
|
||||
},
|
||||
{
|
||||
"name": "The Weeknd"
|
||||
},
|
||||
{
|
||||
"name": "The Chainsmokers"
|
||||
},
|
||||
{
|
||||
"name": "Daft Punk"
|
||||
},
|
||||
{
|
||||
"name": "Marshmello"
|
||||
},
|
||||
{
|
||||
"name": "David Guetta"
|
||||
},
|
||||
{
|
||||
"name": "Calvin Harris"
|
||||
},
|
||||
{
|
||||
"name": "The Weeknd"
|
||||
},
|
||||
{
|
||||
"name": "The Chainsmokers"
|
||||
},
|
||||
{
|
||||
"name": "Daft Punk"
|
||||
},
|
||||
{
|
||||
"name": "Marshmello"
|
||||
},
|
||||
{
|
||||
"name": "David Guetta"
|
||||
},
|
||||
{
|
||||
"name": "Avicii"
|
||||
},
|
||||
{
|
||||
"name": "Kygo"
|
||||
},
|
||||
{
|
||||
"name": "Martin Garrix"
|
||||
},
|
||||
{
|
||||
"name": "Major Lazer"
|
||||
},
|
||||
{
|
||||
"name": "Depeche Mode"
|
||||
}
|
||||
],
|
||||
"name": "electronic, dance"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"name": "Queen"
|
||||
},
|
||||
{
|
||||
"name": "The Beatles"
|
||||
},
|
||||
{
|
||||
"name": "David Bowie"
|
||||
},
|
||||
{
|
||||
"name": "Fleetwood Mac"
|
||||
},
|
||||
{
|
||||
"name": "Pink Floyd"
|
||||
},
|
||||
{
|
||||
"name": "The Rolling Stones"
|
||||
},
|
||||
{
|
||||
"name": "Led Zeppelin"
|
||||
},
|
||||
{
|
||||
"name": "Queen"
|
||||
},
|
||||
{
|
||||
"name": "The Beatles"
|
||||
},
|
||||
{
|
||||
"name": "David Bowie"
|
||||
},
|
||||
{
|
||||
"name": "Fleetwood Mac"
|
||||
},
|
||||
{
|
||||
"name": "Pink Floyd"
|
||||
},
|
||||
{
|
||||
"name": "The Rolling Stones"
|
||||
},
|
||||
{
|
||||
"name": "Led Zeppelin"
|
||||
},
|
||||
{
|
||||
"name": "Elton John"
|
||||
}
|
||||
],
|
||||
"name": "classic rock, rock"
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"name": "Billie Eilish"
|
||||
},
|
||||
{
|
||||
"name": "Ariana Grande"
|
||||
},
|
||||
{
|
||||
"name": "Taylor Swift"
|
||||
},
|
||||
{
|
||||
"name": "Beyoncé"
|
||||
},
|
||||
{
|
||||
"name": "Shawn Mendes"
|
||||
},
|
||||
{
|
||||
"name": "Rihanna"
|
||||
},
|
||||
{
|
||||
"name": "Lana Del Rey"
|
||||
},
|
||||
{
|
||||
"name": "Katy Perry"
|
||||
},
|
||||
{
|
||||
"name": "Lady Gaga"
|
||||
},
|
||||
{
|
||||
"name": "Miley Cyrus"
|
||||
},
|
||||
{
|
||||
"name": "Mark Ronson"
|
||||
},
|
||||
{
|
||||
"name": "Madonna"
|
||||
},
|
||||
{
|
||||
"name": "Lorde"
|
||||
},
|
||||
{
|
||||
"name": "Khalid"
|
||||
},
|
||||
{
|
||||
"name": "Billie Eilish"
|
||||
},
|
||||
{
|
||||
"name": "Ariana Grande"
|
||||
},
|
||||
{
|
||||
"name": "Taylor Swift"
|
||||
},
|
||||
{
|
||||
"name": "Beyoncé"
|
||||
},
|
||||
{
|
||||
"name": "Shawn Mendes"
|
||||
},
|
||||
{
|
||||
"name": "Rihanna"
|
||||
},
|
||||
{
|
||||
"name": "Lana Del Rey"
|
||||
},
|
||||
{
|
||||
"name": "Katy Perry"
|
||||
},
|
||||
{
|
||||
"name": "Lady Gaga"
|
||||
},
|
||||
{
|
||||
"name": "Miley Cyrus"
|
||||
},
|
||||
{
|
||||
"name": "Mark Ronson"
|
||||
},
|
||||
{
|
||||
"name": "Madonna"
|
||||
},
|
||||
{
|
||||
"name": "Lorde"
|
||||
},
|
||||
{
|
||||
"name": "Khalid"
|
||||
},
|
||||
{
|
||||
"name": "Sia"
|
||||
},
|
||||
{
|
||||
"name": "Sam Smith"
|
||||
},
|
||||
{
|
||||
"name": "Halsey"
|
||||
},
|
||||
{
|
||||
"name": "Michael Jackson"
|
||||
},
|
||||
{
|
||||
"name": "Charli XCX"
|
||||
},
|
||||
{
|
||||
"name": "Britney Spears"
|
||||
},
|
||||
{
|
||||
"name": "Dua Lipa"
|
||||
},
|
||||
{
|
||||
"name": "Jonas Brothers"
|
||||
},
|
||||
{
|
||||
"name": "Bruno Mars"
|
||||
},
|
||||
{
|
||||
"name": "Carly Rae Jepsen"
|
||||
},
|
||||
{
|
||||
"name": "P!nk"
|
||||
},
|
||||
{
|
||||
"name": "Adele"
|
||||
}
|
||||
],
|
||||
"name": "pop, female vocalists"
|
||||
}
|
||||
],
|
||||
"name": "Musicians"
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.node circle {
|
||||
fill: #fff;
|
||||
stroke: steelblue;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.node {
|
||||
font: 10px sans-serif;
|
||||
}
|
||||
|
||||
.link {
|
||||
fill: none;
|
||||
stroke: #ccc;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<script src="http://d3js.org/d3.v3.min.js"></script>
|
||||
<script>
|
||||
var diameter = 1100;
|
||||
var tree = d3.layout.tree()
|
||||
.size([360, diameter / 2 - 300])
|
||||
.separation(function (a, b) {
|
||||
return (a.parent == b.parent ? 1 : 2) / a.depth;
|
||||
});
|
||||
var diagonal = d3.svg.diagonal.radial()
|
||||
.projection(function (d) {
|
||||
return [d.y, d.x / 180 * Math.PI];
|
||||
});
|
||||
var svg = d3.select("body").append("svg")
|
||||
.attr("width", diameter)
|
||||
.attr("height", diameter - 150)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
|
||||
d3.json("lastfm.json", function (error, root) {
|
||||
var nodes = tree.nodes(root),
|
||||
links = tree.links(nodes);
|
||||
var link = svg.selectAll(".link")
|
||||
.data(links)
|
||||
.enter().append("path")
|
||||
.attr("class", "link")
|
||||
.attr("d", diagonal);
|
||||
var node = svg.selectAll(".node")
|
||||
.data(nodes)
|
||||
.enter().append("g")
|
||||
.attr("class", "node")
|
||||
.attr("transform", function (d) {
|
||||
return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")";
|
||||
})
|
||||
node.append("circle")
|
||||
.attr("r", 4.5);
|
||||
node.append("text")
|
||||
.attr("dy", ".31em")
|
||||
.attr("text-anchor", function (d) {
|
||||
return d.x < 180 ? "start" : "end";
|
||||
})
|
||||
.attr("transform", function (d) {
|
||||
return d.x < 180 ? "translate(8)" : "rotate(180)translate(-8)";
|
||||
})
|
||||
.text(function (d) {
|
||||
return d.name;
|
||||
});
|
||||
});
|
||||
d3.select(self.frameElement).style("height", diameter - 150 + "px");
|
||||
</script>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.baeldung.algorithms.analysis;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class AnalysisRunnerLiveTest {
|
||||
|
||||
int n = 10;
|
||||
int total = 0;
|
||||
|
||||
@Test
|
||||
public void whenConstantComplexity_thenConstantRuntime() {
|
||||
|
||||
System.out.println("**** n = " + n + " ****");
|
||||
System.out.println();
|
||||
|
||||
// Constant Time
|
||||
System.out.println("**** Constant time ****");
|
||||
|
||||
System.out.println("Hey - your input is: " + n);
|
||||
System.out.println("Running time not dependent on input size!");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLogarithmicComplexity_thenLogarithmicRuntime() {
|
||||
// Logarithmic Time
|
||||
System.out.println("**** Logarithmic Time ****");
|
||||
for (int i = 1; i < n; i = i * 2) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i);
|
||||
total++;
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLinearComplexity_thenLinearRuntime() {
|
||||
// Linear Time
|
||||
System.out.println("**** Linear Time ****");
|
||||
for (int i = 0; i < n; i++) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i);
|
||||
total++;
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNLogNComplexity_thenNLogNRuntime() {
|
||||
// N Log N Time
|
||||
System.out.println("**** nlogn Time ****");
|
||||
total = 0;
|
||||
for (
|
||||
|
||||
int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j < n; j = j * 2) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i + " and " + j);
|
||||
total++;
|
||||
}
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenQuadraticComplexity_thenQuadraticRuntime() {
|
||||
// Quadratic Time
|
||||
System.out.println("**** Quadratic Time ****");
|
||||
total = 0;
|
||||
for (
|
||||
|
||||
int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= n; j++) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i + " and " + j);
|
||||
total++;
|
||||
}
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCubicComplexity_thenCubicRuntime() {
|
||||
// Cubic Time
|
||||
System.out.println("**** Cubic Time ****");
|
||||
total = 0;
|
||||
for (
|
||||
|
||||
int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= n; j++) {
|
||||
for (int k = 1; k <= n; k++) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i + " and " + j + " and " + k);
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenExponentialComplexity_thenExponentialRuntime() {
|
||||
// Exponential Time
|
||||
System.out.println("**** Exponential Time ****");
|
||||
total = 0;
|
||||
for (
|
||||
|
||||
int i = 1; i <= Math.pow(2, n); i++) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i);
|
||||
total++;
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenFactorialComplexity_thenFactorialRuntime() {
|
||||
// Factorial Time
|
||||
System.out.println("**** Factorial Time ****");
|
||||
total = 0;
|
||||
for (
|
||||
|
||||
int i = 1; i <=
|
||||
|
||||
factorial(n); i++) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i);
|
||||
total++;
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
}
|
||||
|
||||
static int factorial(int n) {
|
||||
if (n == 0 || n == 1)
|
||||
return 1;
|
||||
else
|
||||
return n * factorial(n - 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.baeldung.algorithms.checksortedlist;
|
||||
|
||||
import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingComparators;
|
||||
import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingIterativeApproach;
|
||||
import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingOrderingClass;
|
||||
import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingRecursion;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SortedListCheckerUnitTest {
|
||||
|
||||
private List<String> sortedListOfString;
|
||||
private List<String> unsortedListOfString;
|
||||
private List<String> singletonList;
|
||||
|
||||
private List<Employee> employeesSortedByName;
|
||||
private List<Employee> employeesNotSortedByName;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
sortedListOfString = asList("Canada", "HK", "LA", "NJ", "NY");
|
||||
unsortedListOfString = asList("LA", "HK", "NJ", "NY", "Canada");
|
||||
singletonList = Collections.singletonList("NY");
|
||||
|
||||
employeesSortedByName = asList(new Employee(1L, "John"), new Employee(2L, "Kevin"), new Employee(3L, "Mike"));
|
||||
employeesNotSortedByName = asList(new Employee(1L, "Kevin"), new Employee(2L, "John"), new Employee(3L, "Mike"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSortedList_whenUsingIterativeApproach_thenReturnTrue() {
|
||||
assertThat(checkIfSortedUsingIterativeApproach(sortedListOfString)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSingleElementList_whenUsingIterativeApproach_thenReturnTrue() {
|
||||
assertThat(checkIfSortedUsingIterativeApproach(singletonList)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnsortedList_whenUsingIterativeApproach_thenReturnFalse() {
|
||||
assertThat(checkIfSortedUsingIterativeApproach(unsortedListOfString)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSortedListOfEmployees_whenUsingIterativeApproach_thenReturnTrue() {
|
||||
assertThat(checkIfSortedUsingIterativeApproach(employeesSortedByName, Comparator.comparing(Employee::getName))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnsortedListOfEmployees_whenUsingIterativeApproach_thenReturnFalse() {
|
||||
assertThat(checkIfSortedUsingIterativeApproach(employeesNotSortedByName, Comparator.comparing(Employee::getName))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSortedList_whenUsingRecursion_thenReturnTrue() {
|
||||
assertThat(checkIfSortedUsingRecursion(sortedListOfString)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSingleElementList_whenUsingRecursion_thenReturnTrue() {
|
||||
assertThat(checkIfSortedUsingRecursion(singletonList)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnsortedList_whenUsingRecursion_thenReturnFalse() {
|
||||
assertThat(checkIfSortedUsingRecursion(unsortedListOfString)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSortedList_whenUsingGuavaOrdering_thenReturnTrue() {
|
||||
assertThat(checkIfSortedUsingOrderingClass(sortedListOfString)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnsortedList_whenUsingGuavaOrdering_thenReturnFalse() {
|
||||
assertThat(checkIfSortedUsingOrderingClass(unsortedListOfString)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSortedListOfEmployees_whenUsingGuavaOrdering_thenReturnTrue() {
|
||||
assertThat(checkIfSortedUsingOrderingClass(employeesSortedByName, Comparator.comparing(Employee::getName))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnsortedListOfEmployees_whenUsingGuavaOrdering_thenReturnFalse() {
|
||||
assertThat(checkIfSortedUsingOrderingClass(employeesNotSortedByName, Comparator.comparing(Employee::getName))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSortedList_whenUsingGuavaComparators_thenReturnTrue() {
|
||||
assertThat(checkIfSortedUsingComparators(sortedListOfString)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnsortedList_whenUsingGuavaComparators_thenReturnFalse() {
|
||||
assertThat(checkIfSortedUsingComparators(unsortedListOfString)).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.baeldung.algorithms.enumstatemachine;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class LeaveRequestStateUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenLeaveRequest_whenStateEscalated_thenResponsibleIsTeamLeader() {
|
||||
LeaveRequestState state = LeaveRequestState.Escalated;
|
||||
|
||||
assertEquals(state.responsiblePerson(), "Team Leader");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void givenLeaveRequest_whenStateApproved_thenResponsibleIsDepartmentManager() {
|
||||
LeaveRequestState state = LeaveRequestState.Approved;
|
||||
|
||||
assertEquals(state.responsiblePerson(), "Department Manager");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLeaveRequest_whenNextStateIsCalled_thenStateIsChanged() {
|
||||
LeaveRequestState state = LeaveRequestState.Submitted;
|
||||
|
||||
state = state.nextState();
|
||||
assertEquals(state, LeaveRequestState.Escalated);
|
||||
|
||||
state = state.nextState();
|
||||
assertEquals(state, LeaveRequestState.Approved);
|
||||
|
||||
state = state.nextState();
|
||||
assertEquals(state, LeaveRequestState.Approved);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.baeldung.algorithms.graphcycledetection;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.algorithms.graphcycledetection.domain.Graph;
|
||||
import com.baeldung.algorithms.graphcycledetection.domain.Vertex;
|
||||
|
||||
public class GraphCycleDetectionUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenGraph_whenCycleExists_thenReturnTrue() {
|
||||
|
||||
Vertex vertexA = new Vertex("A");
|
||||
Vertex vertexB = new Vertex("B");
|
||||
Vertex vertexC = new Vertex("C");
|
||||
Vertex vertexD = new Vertex("D");
|
||||
|
||||
Graph graph = new Graph();
|
||||
graph.addVertex(vertexA);
|
||||
graph.addVertex(vertexB);
|
||||
graph.addVertex(vertexC);
|
||||
graph.addVertex(vertexD);
|
||||
|
||||
graph.addEdge(vertexA, vertexB);
|
||||
graph.addEdge(vertexB, vertexC);
|
||||
graph.addEdge(vertexC, vertexA);
|
||||
graph.addEdge(vertexD, vertexC);
|
||||
|
||||
assertTrue(graph.hasCycle());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGraph_whenNoCycleExists_thenReturnFalse() {
|
||||
|
||||
Vertex vertexA = new Vertex("A");
|
||||
Vertex vertexB = new Vertex("B");
|
||||
Vertex vertexC = new Vertex("C");
|
||||
Vertex vertexD = new Vertex("D");
|
||||
|
||||
Graph graph = new Graph();
|
||||
graph.addVertex(vertexA);
|
||||
graph.addVertex(vertexB);
|
||||
graph.addVertex(vertexC);
|
||||
graph.addVertex(vertexD);
|
||||
|
||||
graph.addEdge(vertexA, vertexB);
|
||||
graph.addEdge(vertexB, vertexC);
|
||||
graph.addEdge(vertexA, vertexC);
|
||||
graph.addEdge(vertexD, vertexC);
|
||||
|
||||
assertFalse(graph.hasCycle());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.baeldung.algorithms.printtriangles;
|
||||
|
||||
import junitparams.JUnitParamsRunner;
|
||||
import junitparams.Parameters;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(JUnitParamsRunner.class)
|
||||
public class PrintTriangleExamplesUnitTest {
|
||||
|
||||
private static Object[][] rightTriangles() {
|
||||
String expected0 = "";
|
||||
|
||||
String expected2 = "*" + System.lineSeparator()
|
||||
+ "**" + System.lineSeparator();
|
||||
|
||||
String expected5 = "*" + System.lineSeparator()
|
||||
+ "**" + System.lineSeparator()
|
||||
+ "***" + System.lineSeparator()
|
||||
+ "****" + System.lineSeparator()
|
||||
+ "*****" + System.lineSeparator();
|
||||
|
||||
String expected7 = "*" + System.lineSeparator()
|
||||
+ "**" + System.lineSeparator()
|
||||
+ "***" + System.lineSeparator()
|
||||
+ "****" + System.lineSeparator()
|
||||
+ "*****" + System.lineSeparator()
|
||||
+ "******" + System.lineSeparator()
|
||||
+ "*******" + System.lineSeparator();
|
||||
|
||||
return new Object[][] {
|
||||
{ 0, expected0 },
|
||||
{ 2, expected2 },
|
||||
{ 5, expected5 },
|
||||
{ 7, expected7 }
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
@Parameters(method = "rightTriangles")
|
||||
public void whenPrintARightTriangleIsCalled_ThenTheCorrectStringIsReturned(int nrOfRows, String expected) {
|
||||
String actual = PrintTriangleExamples.printARightTriangle(nrOfRows);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
private static Object[][] isoscelesTriangles() {
|
||||
String expected0 = "";
|
||||
|
||||
String expected2 = " *" + System.lineSeparator()
|
||||
+ "***" + System.lineSeparator();
|
||||
|
||||
String expected5 = " *" + System.lineSeparator()
|
||||
+ " ***" + System.lineSeparator()
|
||||
+ " *****" + System.lineSeparator()
|
||||
+ " *******" + System.lineSeparator()
|
||||
+ "*********" + System.lineSeparator();
|
||||
|
||||
String expected7 = " *" + System.lineSeparator()
|
||||
+ " ***" + System.lineSeparator()
|
||||
+ " *****" + System.lineSeparator()
|
||||
+ " *******" + System.lineSeparator()
|
||||
+ " *********" + System.lineSeparator()
|
||||
+ " ***********" + System.lineSeparator()
|
||||
+ "*************" + System.lineSeparator();
|
||||
|
||||
return new Object[][] {
|
||||
{ 0, expected0 },
|
||||
{ 2, expected2 },
|
||||
{ 5, expected5 },
|
||||
{ 7, expected7 }
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
@Parameters(method = "isoscelesTriangles")
|
||||
public void whenPrintAnIsoscelesTriangleIsCalled_ThenTheCorrectStringIsReturned(int nrOfRows, String expected) {
|
||||
String actual = PrintTriangleExamples.printAnIsoscelesTriangle(nrOfRows);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Parameters(method = "isoscelesTriangles")
|
||||
public void whenPrintAnIsoscelesTriangleUsingStringUtilsIsCalled_ThenTheCorrectStringIsReturned(int nrOfRows, String expected) {
|
||||
String actual = PrintTriangleExamples.printAnIsoscelesTriangleUsingStringUtils(nrOfRows);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Parameters(method = "isoscelesTriangles")
|
||||
public void whenPrintAnIsoscelesTriangleUsingSubstringIsCalled_ThenTheCorrectStringIsReturned(int nrOfRows, String expected) {
|
||||
String actual = PrintTriangleExamples.printAnIsoscelesTriangleUsingSubstring(nrOfRows);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.algorithms.romannumerals;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class RomanArabicConverterUnitTest {
|
||||
|
||||
@Test
|
||||
public void given2018Roman_WhenConvertingToArabic_ThenReturn2018() {
|
||||
|
||||
String roman2018 = "MMXVIII";
|
||||
|
||||
int result = RomanArabicConverter.romanToArabic(roman2018);
|
||||
|
||||
assertThat(result).isEqualTo(2018);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void given1999Arabic_WhenConvertingToRoman_ThenReturnMCMXCIX() {
|
||||
|
||||
int arabic1999 = 1999;
|
||||
|
||||
String result = RomanArabicConverter.arabicToRoman(arabic1999);
|
||||
|
||||
assertThat(result).isEqualTo("MCMXCIX");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.baeldung.algorithms.twopointertechnique;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class LinkedListFindMiddleUnitTest {
|
||||
|
||||
LinkedListFindMiddle linkedListFindMiddle = new LinkedListFindMiddle();
|
||||
|
||||
@Test
|
||||
public void givenLinkedListOfMyNodes_whenLinkedListFindMiddle_thenCorrect() {
|
||||
|
||||
MyNode<String> head = createNodesList(8);
|
||||
|
||||
assertThat(linkedListFindMiddle.findMiddle(head)).isEqualTo("4");
|
||||
|
||||
head = createNodesList(9);
|
||||
|
||||
assertThat(linkedListFindMiddle.findMiddle(head)).isEqualTo("5");
|
||||
}
|
||||
|
||||
private static MyNode<String> createNodesList(int n) {
|
||||
|
||||
MyNode<String> head = new MyNode<String>("1");
|
||||
MyNode<String> current = head;
|
||||
|
||||
for (int i = 2; i <= n; i++) {
|
||||
MyNode<String> newNode = new MyNode<String>(String.valueOf(i));
|
||||
current.setNext(newNode);
|
||||
current = newNode;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.algorithms.twopointertechnique;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class RotateArrayUnitTest {
|
||||
|
||||
private RotateArray rotateArray = new RotateArray();
|
||||
|
||||
private int[] inputArray;
|
||||
|
||||
private int step;
|
||||
|
||||
@Test
|
||||
public void givenAnArrayOfIntegers_whenRotateKsteps_thenCorrect() {
|
||||
|
||||
inputArray = new int[] { 1, 2, 3, 4, 5, 6, 7 };
|
||||
step = 4;
|
||||
|
||||
rotateArray.rotate(inputArray, step);
|
||||
|
||||
assertThat(inputArray).containsExactly(new int[] { 4, 5, 6, 7, 1, 2, 3 });
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.baeldung.algorithms.twopointertechnique;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class TwoSumUnitTest {
|
||||
|
||||
private TwoSum twoSum = new TwoSum();
|
||||
|
||||
private int[] sortedArray;
|
||||
|
||||
private int targetValue;
|
||||
|
||||
@Test
|
||||
public void givenASortedArrayOfIntegers_whenTwoSumSlow_thenPairExists() {
|
||||
|
||||
sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 };
|
||||
|
||||
targetValue = 12;
|
||||
|
||||
assertTrue(twoSum.twoSumSlow(sortedArray, targetValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenASortedArrayOfIntegers_whenTwoSumSlow_thenPairDoesNotExists() {
|
||||
|
||||
sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 };
|
||||
|
||||
targetValue = 20;
|
||||
|
||||
assertFalse(twoSum.twoSumSlow(sortedArray, targetValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenASortedArrayOfIntegers_whenTwoSum_thenPairExists() {
|
||||
|
||||
sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 };
|
||||
|
||||
targetValue = 12;
|
||||
|
||||
assertTrue(twoSum.twoSum(sortedArray, targetValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenASortedArrayOfIntegers_whenTwoSum_thenPairDoesNotExists() {
|
||||
|
||||
sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 };
|
||||
|
||||
targetValue = 20;
|
||||
|
||||
assertFalse(twoSum.twoSum(sortedArray, targetValue));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.baeldung.counter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
|
||||
import com.baeldung.counter.CounterUtil.MutableInteger;
|
||||
|
||||
@Fork(value = 1, warmups = 3)
|
||||
@BenchmarkMode(Mode.All)
|
||||
public class CounterStatistics {
|
||||
|
||||
private static final Map<String, Integer> counterMap = new HashMap<>();
|
||||
private static final Map<String, MutableInteger> counterWithMutableIntMap = new HashMap<>();
|
||||
private static final Map<String, int[]> counterWithIntArrayMap = new HashMap<>();
|
||||
private static final Map<String, Long> counterWithLongWrapperMap = new HashMap<>();
|
||||
private static final Map<String, Long> counterWithLongWrapperStreamMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
CounterUtil.COUNTRY_NAMES = new String[10000];
|
||||
final String prefix = "NewString";
|
||||
Random random = new Random();
|
||||
for (int i=0; i<10000; i++) {
|
||||
CounterUtil.COUNTRY_NAMES[i] = new String(prefix + random.nextInt(1000));
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void wrapperAsCounter() {
|
||||
CounterUtil.counterWithWrapperObject(counterMap);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void lambdaExpressionWithWrapper() {
|
||||
CounterUtil.counterWithLambdaAndWrapper(counterWithLongWrapperMap);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void parallelStreamWithWrapper() {
|
||||
CounterUtil.counterWithParallelStreamAndWrapper(counterWithLongWrapperStreamMap);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void mutableIntegerAsCounter() {
|
||||
CounterUtil.counterWithMutableInteger(counterWithMutableIntMap);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void primitiveArrayAsCounter() {
|
||||
CounterUtil.counterWithPrimitiveArray(counterWithIntArrayMap);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
org.openjdk.jmh.Main.main(args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.baeldung.counter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.counter.CounterUtil.MutableInteger;
|
||||
|
||||
public class CounterUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenMapWithWrapperAsCounter_runsSuccessfully() {
|
||||
Map<String, Integer> counterMap = new HashMap<>();
|
||||
CounterUtil.counterWithWrapperObject(counterMap);
|
||||
|
||||
assertEquals(3, counterMap.get("China")
|
||||
.intValue());
|
||||
assertEquals(2, counterMap.get("India")
|
||||
.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenMapWithLambdaAndWrapperCounter_runsSuccessfully() {
|
||||
Map<String, Long> counterMap = new HashMap<>();
|
||||
CounterUtil.counterWithLambdaAndWrapper(counterMap);
|
||||
|
||||
assertEquals(3l, counterMap.get("China")
|
||||
.longValue());
|
||||
assertEquals(2l, counterMap.get("India")
|
||||
.longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenMapWithMutableIntegerCounter_runsSuccessfully() {
|
||||
Map<String, MutableInteger> counterMap = new HashMap<>();
|
||||
CounterUtil.counterWithMutableInteger(counterMap);
|
||||
assertEquals(3, counterMap.get("China")
|
||||
.getCount());
|
||||
assertEquals(2, counterMap.get("India")
|
||||
.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenMapWithPrimitiveArray_runsSuccessfully() {
|
||||
Map<String, int[]> counterMap = new HashMap<>();
|
||||
CounterUtil.counterWithPrimitiveArray(counterMap);
|
||||
assertEquals(3, counterMap.get("China")[0]);
|
||||
assertEquals(2, counterMap.get("India")[0]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.baeldung.counter;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class CounterUtil {
|
||||
|
||||
public static String[] COUNTRY_NAMES = { "China", "Australia", "India", "USA", "USSR", "UK", "China", "France", "Poland", "Austria", "India", "USA", "Egypt", "China" };
|
||||
|
||||
public static void counterWithWrapperObject(Map<String, Integer> counterMap) {
|
||||
for (String country : COUNTRY_NAMES) {
|
||||
counterMap.compute(country, (k, v) -> v == null ? 1 : v + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public static void counterWithLambdaAndWrapper(Map<String, Long> counterMap) {
|
||||
Stream.of(COUNTRY_NAMES)
|
||||
.collect(Collectors.groupingBy(k -> k, () -> counterMap, Collectors.counting()));
|
||||
}
|
||||
|
||||
public static void counterWithParallelStreamAndWrapper(Map<String, Long> counterMap) {
|
||||
Stream.of(COUNTRY_NAMES)
|
||||
.parallel()
|
||||
.collect(Collectors.groupingBy(k -> k, () -> counterMap, Collectors.counting()));
|
||||
}
|
||||
|
||||
public static class MutableInteger {
|
||||
int count;
|
||||
|
||||
public MutableInteger(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
this.count++;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return this.count;
|
||||
}
|
||||
}
|
||||
|
||||
public static void counterWithMutableInteger(Map<String, MutableInteger> counterMap) {
|
||||
for (String country : COUNTRY_NAMES) {
|
||||
counterMap.compute(country, (k, v) -> v == null ? new MutableInteger(0) : v)
|
||||
.increment();
|
||||
}
|
||||
}
|
||||
|
||||
public static void counterWithPrimitiveArray(Map<String, int[]> counterMap) {
|
||||
for (String country : COUNTRY_NAMES) {
|
||||
counterMap.compute(country, (k, v) -> v == null ? new int[] { 0 } : v)[0]++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.baeldung.folding;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class FoldingHashUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenStringJavaLanguage_whenSize2Capacity100000_then48933() throws Exception {
|
||||
final FoldingHash hasher = new FoldingHash();
|
||||
final int value = hasher.hash("Java language", 2, 100_000);
|
||||
assertEquals(value, 48933);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStringVaJaLanguage_whenSize2Capacity100000_thenSameAsJavaLanguage() throws Exception {
|
||||
final FoldingHash hasher = new FoldingHash();
|
||||
final int java = hasher.hash("Java language", 2, 100_000);
|
||||
final int vaja = hasher.hash("vaJa language", 2, 100_000);
|
||||
assertTrue(java == vaja);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSingleElementArray_whenOffset0Size2_thenSingleElement() throws Exception {
|
||||
final FoldingHash hasher = new FoldingHash();
|
||||
final int[] value = hasher.extract(new int[] { 5 }, 0, 2);
|
||||
assertArrayEquals(new int[] { 5 }, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFiveElementArray_whenOffset0Size3_thenFirstThreeElements() throws Exception {
|
||||
final FoldingHash hasher = new FoldingHash();
|
||||
final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 0, 3);
|
||||
assertArrayEquals(new int[] { 1, 2, 3 }, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFiveElementArray_whenOffset1Size2_thenTwoElements() throws Exception {
|
||||
final FoldingHash hasher = new FoldingHash();
|
||||
final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 1, 2);
|
||||
assertArrayEquals(new int[] { 2, 3 }, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFiveElementArray_whenOffset2SizeTooBig_thenElementsToTheEnd() throws Exception {
|
||||
final FoldingHash hasher = new FoldingHash();
|
||||
final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 2, 2000);
|
||||
assertArrayEquals(new int[] { 3, 4, 5 }, value);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user