Table of Contents
- Day 1 - Generating a random number within a specific range.
- Day 2 - Formatting a
LocalDateTime
object. - Day 3 - Scheduling a task to run every 2 seconds.
- Day 4 - Removing items from a List.
- Day 5 - Creating a list with filtered items from other lists.
- Day 6 - Running a task asynchronously.
- Day 7 - Formatting a message using
MessageFormat
. - Day 8 - Creating a thread pool to run tasks simultaneously and reuse threads.
- Day 9 - Creating a valued Enum.
- Day 10 - Using Google’s Jimfs to write tests that use an in-memory file system.
- Day 11 - Sorting a
java.util.Map
by its values. - Day 12 - Using
Callable
andFuture
to run tasks in parallel. - Day 13 - Creating a lazily initialized Singleton.
- Day 14 - Never pass a
double
as argument when constructingBigDecimal
objects. - Day 15 - Builder Pattern
- Day 16 - Joining Strings.
- Day 17 - Splitting Strings.
- Day 18 - Finding the maximum value from a
Collection
. - Day 19 - A
Map
implementation that keeps the elements in the same order that they were inserted. - Day 20 - Reversing a
String
- Day 21 - Using WireMock to mock a web server.
- Day 22 - Mapping and reducing from a
List
. - Day 23 - Loading properties from a file.
- Day 24 - Running operating system commands.
- Day 25 - Pattern Matching for
instanceof
in JDK 16. - Day 26 - Using
Optional
whennull
is a valid return value. - Day 27 - Printing a
List
: one item per line. - Day 28 - Sorting a
List
by a specific attribute.
A little of Java content every day for a hundred days.
If you have any questions, ask me on my social media.
import java.security.SecureRandom;
public final class Day001 {
public static final SecureRandom SECURE_RANDOM = new SecureRandom();
public static void main(String[] args) {
System.out.println("Generating a number between 50 and 100...");
System.out.println(randomNumberBetween(50, 100));
}
private static int randomNumberBetween(int minimum, int maximum) {
return SECURE_RANDOM.nextInt(maximum - minimum) + minimum;
}
}
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public final class Day002 {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
public static void main(String[] args) {
LocalDateTime currentDateTime = LocalDateTime.now();
String formattedDateTime = currentDateTime.format(FORMATTER);
System.out.println(formattedDateTime);
}
}
import java.time.LocalTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Day003 {
private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
public static void main(String[] args) throws InterruptedException {
var day003 = new Day003();
day003.printCurrentTimeEvery2Seconds();
Thread.sleep(15_000);
day003.stopPrinting();
}
public void printCurrentTimeEvery2Seconds() {
Runnable task = () -> System.out.println(LocalTime.now());
scheduledExecutorService.scheduleAtFixedRate(task, 0, 2, TimeUnit.SECONDS);
}
public void stopPrinting() {
scheduledExecutorService.shutdown();
}
}
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class Day004 {
public static void main(String[] args) {
List<Person> beatles = new ArrayList<>();
beatles.add(new Person("1", "John Lennon", LocalDate.of(1940, 10, 9)));
beatles.add(new Person("2", "Paul McCartney", LocalDate.of(1942, 6, 18)));
beatles.add(new Person("3", "George Harrison", LocalDate.of(1943, 2, 25)));
beatles.add(new Person("4", "Ringo Starr", LocalDate.of(1940, 7, 7)));
removeItemUsingEquals(beatles);
removeItemUsingAnSpecificFilter(beatles);
System.out.println(beatles);
}
private static void removeItemUsingAnSpecificFilter(List<Person> beatles) {
beatles.removeIf(person -> "George Harrison".equals(person.getName()));
}
private static void removeItemUsingEquals(List<Person> beatles) {
var lennon = new Person("1", "John Lennon", LocalDate.of(1940, 10, 9));
beatles.remove(lennon);
}
static class Person {
private final String id;
private final String name;
private final LocalDate dateOfBirth;
Person(String id, String name, LocalDate dateOfBirth) {
this.id = id;
this.name = name;
this.dateOfBirth = dateOfBirth;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
var person = (Person) o;
return Objects.equals(id, person.id) && Objects.equals(name, person.name) && Objects.equals(dateOfBirth, person.dateOfBirth);
}
@Override
public int hashCode() {
return Objects.hash(id, name, dateOfBirth);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
}
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Day005 {
private static final String GUITAR = "Guitar";
private static final String DRUMS = "Drums";
private static final String BASS = "Bass";
private static final String VOCALS = "Vocals";
private static final String KEYBOARDS = "Keyboards";
public static void main(String[] args) {
List<BandMember> pinkFloyd = List.of(
new BandMember("David Gilmour", GUITAR),
new BandMember("Roger Waters", BASS),
new BandMember("Richard Wright", KEYBOARDS),
new BandMember("Nick Mason", DRUMS)
);
List<BandMember> ironMaiden = List.of(
new BandMember("Bruce Dickinson", VOCALS),
new BandMember("Steve Harris", BASS),
new BandMember("Adrian Smith", GUITAR),
new BandMember("Dave Murray", GUITAR),
new BandMember("Nicko McBrain", DRUMS)
);
List<BandMember> blackSabbath = List.of(
new BandMember("Ozzy Osbourne", VOCALS),
new BandMember("Geezer Butler", BASS),
new BandMember("Toni Iommi", GUITAR),
new BandMember("Bill Ward", DRUMS)
);
Stream<BandMember> musicians = Stream.concat(Stream.concat(pinkFloyd.stream(), ironMaiden.stream()), blackSabbath.stream());
List<String> guitarPlayers = musicians.filter(bandMember -> GUITAR.equals(bandMember.instrument))
.map(BandMember::name)
.collect(Collectors.toList());
System.out.println(guitarPlayers);
}
static record BandMember(String name, String instrument) {
}
}
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.util.concurrent.TimeUnit.SECONDS;
public class Day006 {
private static final Logger LOGGER = Logger.getLogger(Day006.class.getName());
public static void main(String[] args) {
CompletableFuture.runAsync(Day006::task);
LOGGER.info("Message from the main thread. Note that this message is logged before the async task ends.");
LOGGER.info("Waiting for the async task to end.");
boolean isQuiecent = ForkJoinPool.commonPool().awaitQuiescence(5, SECONDS);
if (isQuiecent) {
LOGGER.info("Async task ended.");
} else {
LOGGER.log(Level.SEVERE, "The async task is taking too long to finish. This program will end anyway.");
}
}
private static void task() {
LOGGER.info("Async task starting. This message is logged by the async task thread");
try {
Thread.sleep(1000);
LOGGER.info("Async task is ending. This message is logged by the async task thread");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOGGER.log(Level.SEVERE, "The async task thread was interrupted.", e);
}
}
}
import java.text.MessageFormat;
public class Day007 {
public static void main(String[] args) {
showMessage("Java", "is", "great");
}
private static void showMessage(String param1, String param2, String param3) {
String message = MessageFormat.format("This message contains 3 parameters. The #1 is ''{0}'', the #2 is ''{1}'', and the #3 is ''{2}''.",
param1, param2, param3);
System.out.println(message);
}
}
import java.security.SecureRandom;
import java.text.MessageFormat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
public class Day008 {
private static final Logger LOGGER = Logger.getLogger(Day008.class.getName());
private static final SecureRandom RANDOM = new SecureRandom();
public static void main(String[] args) {
LOGGER.info("Creating a thread pool with 5 threads");
ExecutorService executor = Executors.newFixedThreadPool(5);
/*
* Will submit 15 tasks. Note that there's only 5 threads to run all of them in our thread pool.
* So the first 5 tasks will run simultaneously and 10 tasks will wait in the queue until a thread is available.
*/
LOGGER.info("Starting tasks submissions.");
try {
for (var i = 1; i <= 15; i++) {
int taskId = i;
LOGGER.info(() -> MessageFormat.format("Will submit task {0}.", taskId));
executor.submit(() -> task(taskId));
}
} finally {
executor.shutdown();
}
}
private static void task(int taskId) {
LOGGER.info(() -> MessageFormat.format("Running task {0}.", taskId));
simulateLongProcessing();
LOGGER.info(() -> MessageFormat.format("Task {0} has finished.", taskId));
}
private static void simulateLongProcessing() {
try {
Thread.sleep((RANDOM.nextInt(3) + 10) * 1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(MessageFormat.format("Thread {0} was interrupted.", Thread.currentThread().getName()), e);
}
}
}
public class Day009 {
public static void main(String[] args) {
for (Gender gender : Gender.values()) {
System.out.printf("The value of %s is %s%n", gender, gender.getValue());
}
}
public enum Gender {
FEMALE('f'),
MALE('m');
private final char value;
Gender(char value) {
this.value = value;
}
public char getValue() {
return value;
}
}
}
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.file.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
class Day010Test {
@Test
void fileDoesNotExist() {
FileSystem fileSystem = Jimfs.newFileSystem(Configuration.unix());
Path directory = fileSystem.getPath("/directory");
Path file = directory.resolve(fileSystem.getPath("myfile.txt"));
assertThatCode(() -> Files.write(file, "thegreatapi.com".getBytes(), StandardOpenOption.WRITE))
.isInstanceOf(NoSuchFileException.class);
}
@Test
void fileExists() throws IOException {
FileSystem fileSystem = Jimfs.newFileSystem(Configuration.unix());
Path directory = fileSystem.getPath("/directory");
Path file = directory.resolve(fileSystem.getPath("myfile.txt"));
Files.createDirectory(directory);
Files.createFile(file);
assertThatCode(() -> Files.write(file, "thegreatapi.com".getBytes(), StandardOpenOption.WRITE))
.doesNotThrowAnyException();
assertThat(Files.readString(file))
.isEqualTo("thegreatapi.com");
}
}
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
public class Day011 {
public static void main(String[] args) {
Map<String, Integer> unsortedMap = Map.of(
"three", 3,
"one", 1,
"four", 4,
"five", 5,
"two", 2
);
Map<String, Integer> sortedMap = sortByValue(unsortedMap);
System.out.println(sortedMap);
}
private static Map<String, Integer> sortByValue(Map<String, Integer> unsortedMap) {
TreeMap<Integer, String> treeMap = new TreeMap<>();
unsortedMap.forEach((key, value) -> treeMap.put(value, key));
Map<String, Integer> sortedMap = new LinkedHashMap<>();
treeMap.forEach((key, value) -> sortedMap.put(value, key));
return Collections.unmodifiableMap(sortedMap);
}
}
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Logger;
public class Day012 {
private static final Logger LOGGER = Logger.getLogger(Day012.class.getName());
public static void main(String[] args) throws InterruptedException {
var executorService = Executors.newSingleThreadExecutor();
try {
Callable<Integer> callable = Day012::doALongCalculation;
Future<Integer> future = executorService.submit(callable);
doOtherThingWhileCalculating();
LOGGER.info("Will get the calculated value. Note that the value will be get immediately");
LOGGER.info("Calculated value: " + future.get());
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}
private static int doALongCalculation() throws InterruptedException {
Thread.sleep(5000L);
return 42;
}
private static void doOtherThingWhileCalculating() throws InterruptedException {
Thread.sleep(7000L);
}
}
import java.time.LocalDateTime;
public final class MySingletonClass {
private final LocalDateTime creationDateTime;
private MySingletonClass(LocalDateTime creationDateTime) {
this.creationDateTime = creationDateTime;
}
public LocalDateTime getCreationDateTime() {
return creationDateTime;
}
public static MySingletonClass getInstance() {
return InstanceHolder.INSTANCE;
}
private static final class InstanceHolder {
static final MySingletonClass INSTANCE = new MySingletonClass(LocalDateTime.now());
}
}
import java.math.BigDecimal;
public class Day014 {
public static void main(String[] args) {
// Prints 1.229999999999999982236431605997495353221893310546875
System.out.println(new BigDecimal(1.23));
// Prints 1.23
System.out.println(new BigDecimal("1.23"));
// Prints 1.23
System.out.println(BigDecimal.valueOf(1.23));
}
}
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class Day015 {
public static void main(String[] args) {
Person john = Person.builder()
.name("John")
.children(List.of(
Person.builder()
.name("Amanda")
.petName("Toto")
.build()
))
.build();
System.out.println(john);
}
public static class Person {
private final String name;
private final List<Person> children;
@Nullable
private final String petName;
private Person(Builder builder) {
name = Objects.requireNonNull(builder.name);
children = builder.children != null ? builder.children : List.of();
petName = builder.petName;
}
public String getName() {
return name;
}
public List<Person> getChildren() {
return children;
}
@Nullable
public String getPetName() {
return petName;
}
public static Builder builder() {
return new Builder();
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", children=" + children +
", petName='" + petName + '\'' +
'}';
}
}
public static final class Builder {
private String name;
private List<Person> children;
@Nullable
private String petName;
private Builder() {
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder children(List<Person> children) {
this.children = Collections.unmodifiableList(children);
return this;
}
public Builder petName(String petName) {
this.petName = petName;
return this;
}
public Person build() {
return new Person(this);
}
}
}
public class Day016 {
public static void main(String[] args) {
System.out.println(createSql("id", "name", "coutry", "gender"));
}
private static String createSql(String... columns) {
return new StringBuilder("SELECT ")
.append(String.join(", ", columns))
.append(" FROM PEOPLE")
.toString();
}
}
import java.util.regex.Pattern;
public class Day017 {
private static final Pattern REGEX = Pattern.compile(", ");
public static void main(String[] args) {
System.out.println("Simple split: ");
for (String column : simpleSplit()) {
System.out.println(column);
}
System.out.println("Performant split: ");
for (String column : performantSplit()) {
System.out.println(column);
}
}
private static String[] simpleSplit() {
return "id, name, country, gender".split(", ");
}
// If you will split frequently, prefer this implementation.
private static String[] performantSplit() {
return REGEX.split("id, name, country, gender");
}
}
import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;
public class Day018 {
public static void main(String[] args) {
System.out.println(max(List.of(6, 3, 1, 8, 3, 9, 2, 7)));
}
private static Integer max(Collection<Integer> collection) {
return collection.stream()
.max(Integer::compareTo)
.orElseThrow(NoSuchElementException::new);
}
}
import java.util.LinkedHashMap;
import java.util.Map;
public class Day019 {
public static void main(String[] args) {
Map<Integer, String> map = new LinkedHashMap<>();
map.put(5, "five");
map.put(4, "four");
map.put(3, "three");
map.put(2, "two");
map.put(1, "one");
map.forEach((key, value) -> System.out.println(key + ": " + value));
}
}
public class Day020 {
public static void main(String[] args) {
var original = "moc.ipataergeht";
var reversed = new StringBuilder(original).reverse().toString();
System.out.println(reversed);
}
}
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
import static org.junit.jupiter.api.Assertions.assertEquals;
class Day021Test {
private WireMockServer server;
@BeforeEach
void setUp() {
server = new WireMockServer(WireMockConfiguration.wireMockConfig().dynamicPort());
server.start();
}
@Test
void test() throws Exception {
mockWebServer();
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:" + server.port() + "/my/resource"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
assertEquals("TheGreatAPI.com", response.body());
}
private void mockWebServer() {
server.stubFor(get("/my/resource")
.willReturn(ok()
.withBody("TheGreatAPI.com")));
}
@AfterEach
void tearDown() {
server.shutdownServer();
}
}
import java.util.List;
public class Day022 {
public static void main(String[] args) {
List<Order> orders = readOrders();
String bands = orders.stream()
.map(Order::customer)
.map(Customer::band)
.reduce((band1, band2) -> String.join(";", band1, band2))
.orElse("None");
System.out.println(bands);
/* Prints:
Pink Floyd;Black Sabbath;Ozzy Osbourne
*/
}
private static List<Order> readOrders() {
var gilmour = new Customer("David Gilmour", "Pink Floyd");
var iommi = new Customer("Toni Iommi", "Black Sabbath");
var rhoads = new Customer("Randy Rhoads", "Ozzy Osbourne");
var strato = new Product("Fender", "Stratocaster");
var sg = new Product("Gibson", "SG");
var lesPaul = new Product("Gibson", "Les Paul");
var rr = new Product("Jackson", "RR");
return List.of(
new Order(gilmour, List.of(strato)),
new Order(iommi, List.of(sg)),
new Order(rhoads, List.of(lesPaul, rr))
);
}
static record Customer(String name, String band) {
}
static record Product(String brand, String modelName) {
}
static record Order(Customer customer, List<Product> products) {
}
}
import java.io.IOException;
import java.util.Properties;
public class Day023 {
public static void main(String[] args) throws IOException {
var properties = new Properties();
try (var reader = Day023.class.getClassLoader().getResourceAsStream("config.properties")) {
properties.load(reader);
}
System.out.println(properties);
}
}
package com.thegreatapi.ahundreddaysofjava.day024;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import static java.util.concurrent.TimeUnit.SECONDS;
public class Day024 {
public static void main(String[] args) throws IOException, InterruptedException {
var process = new ProcessBuilder("ls").start();
try (var stdOutReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
var stdErrReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
if (process.waitFor(5, SECONDS)) {
int exitValue = process.exitValue();
if (exitValue == 0) {
stdOutReader.lines().forEach(System.out::println);
} else {
stdErrReader.lines().forEach(System.err::println);
}
} else {
throw new RuntimeException("Timeout");
}
}
}
}
public class Day025 {
public static void main(String[] args) {
Number n = 6;
// Instead of doing:
if (n instanceof Integer) {
Integer i = (Integer) n;
print(i);
}
// Just do:
if (n instanceof Integer i) {
print(i);
}
}
private static void print(Integer i) {
System.out.println(i);
}
}
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Optional;
public class Day026 {
public static void main(String[] args) {
// Instead of doing:
String nullableValue = getNullableValue();
if (nullableValue != null) {
System.out.println(nullableValue.length());
} else {
System.out.println(0);
}
// Just do:
System.out.println(getOptionalValue().map(String::length).orElse(0));
}
@Nonnull
private static Optional<String> getOptionalValue() {
return Optional.empty();
}
@Nullable
private static String getNullableValue() {
return null;
}
}
import java.util.List;
public class Day027 {
public static void main(String[] args) {
List<Player> players = createList();
String message = players.stream()
.map(Player::toString)
.reduce((p1, p2) -> p1 + System.lineSeparator() + p2)
.orElse("");
System.out.println(message);
}
private static List<Player> createList() {
Player messi = new Player("Lionel Messi", "Barcelona", "Argentina", 42);
Player cr7 = new Player("Cristiano Ronaldo", "Juventus", "Portugal", 50);
Player neymar = new Player("Neymar Jr.", "PSG", "Brazil", 41);
return List.of(messi, cr7, neymar);
}
private record Player(String name, String club, String coutry, int numberOfGoals) {
}
}
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class Day028 {
public static void main(String[] args) {
Player messi = new Player("Lionel Messi", "Barcelona", "Argentina", 42);
Player cr7 = new Player("Cristiano Ronaldo", "Juventus", "Portugal", 50);
Player neymar = new Player("Neymar Jr.", "PSG", "Brazil", 41);
List<Player> players = Arrays.asList(messi, cr7, neymar);
players.sort(Comparator.comparing(Player::numberOfGoals).reversed());
System.out.println("Top Scorers:");
players.forEach(System.out::println);
}
private record Player(String name, String club, String coutry, int numberOfGoals) {
}
}