Merge branch 'master' into feature/ktln-43/working-with-lists-in-kotlin
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
package com.baeldung.algorithms.play2048;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Board {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Board.class);
|
||||
|
||||
private final int[][] board;
|
||||
|
||||
private final int score;
|
||||
|
||||
public Board(int size) {
|
||||
assert(size > 0);
|
||||
|
||||
this.board = new int[size][];
|
||||
this.score = 0;
|
||||
|
||||
for (int x = 0; x < size; ++x) {
|
||||
this.board[x] = new int[size];
|
||||
for (int y = 0; y < size; ++y) {
|
||||
board[x][y] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Board(int[][] board, int score) {
|
||||
this.score = score;
|
||||
this.board = new int[board.length][];
|
||||
|
||||
for (int x = 0; x < board.length; ++x) {
|
||||
this.board[x] = Arrays.copyOf(board[x], board[x].length);
|
||||
}
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return board.length;
|
||||
}
|
||||
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public int getCell(Cell cell) {
|
||||
int x = cell.getX();
|
||||
int y = cell.getY();
|
||||
assert(x >= 0 && x < board.length);
|
||||
assert(y >= 0 && y < board.length);
|
||||
|
||||
return board[x][y];
|
||||
}
|
||||
|
||||
public boolean isEmpty(Cell cell) {
|
||||
return getCell(cell) == 0;
|
||||
}
|
||||
|
||||
public List<Cell> emptyCells() {
|
||||
List<Cell> result = new ArrayList<>();
|
||||
for (int x = 0; x < board.length; ++x) {
|
||||
for (int y = 0; y < board[x].length; ++y) {
|
||||
Cell cell = new Cell(x, y);
|
||||
if (isEmpty(cell)) {
|
||||
result.add(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Board placeTile(Cell cell, int number) {
|
||||
if (!isEmpty(cell)) {
|
||||
throw new IllegalArgumentException("That cell is not empty");
|
||||
}
|
||||
|
||||
Board result = new Board(this.board, this.score);
|
||||
result.board[cell.getX()][cell.getY()] = number;
|
||||
return result;
|
||||
}
|
||||
|
||||
public Board move(Move move) {
|
||||
// Clone the board
|
||||
int[][] tiles = new int[this.board.length][];
|
||||
for (int x = 0; x < this.board.length; ++x) {
|
||||
tiles[x] = Arrays.copyOf(this.board[x], this.board[x].length);
|
||||
}
|
||||
|
||||
LOG.debug("Before move: {}", Arrays.deepToString(tiles));
|
||||
// If we're doing an Left/Right move then transpose the board to make it a Up/Down move
|
||||
if (move == Move.LEFT || move == Move.RIGHT) {
|
||||
tiles = transpose(tiles);
|
||||
LOG.debug("After transpose: {}", Arrays.deepToString(tiles));
|
||||
}
|
||||
// If we're doing a Right/Down move then reverse the board.
|
||||
// With the above we're now always doing an Up move
|
||||
if (move == Move.DOWN || move == Move.RIGHT) {
|
||||
tiles = reverse(tiles);
|
||||
LOG.debug("After reverse: {}", Arrays.deepToString(tiles));
|
||||
}
|
||||
LOG.debug("Ready to move: {}", Arrays.deepToString(tiles));
|
||||
|
||||
// Shift everything up
|
||||
int[][] result = new int[tiles.length][];
|
||||
int newScore = 0;
|
||||
for (int x = 0; x < tiles.length; ++x) {
|
||||
LinkedList<Integer> thisRow = new LinkedList<>();
|
||||
for (int y = 0; y < tiles[0].length; ++y) {
|
||||
if (tiles[x][y] > 0) {
|
||||
thisRow.add(tiles[x][y]);
|
||||
}
|
||||
}
|
||||
|
||||
LOG.debug("Unmerged row: {}", thisRow);
|
||||
LinkedList<Integer> newRow = new LinkedList<>();
|
||||
while (thisRow.size() >= 2) {
|
||||
int first = thisRow.pop();
|
||||
int second = thisRow.peek();
|
||||
LOG.debug("Looking at numbers {} and {}", first, second);
|
||||
if (second == first) {
|
||||
LOG.debug("Numbers match, combining");
|
||||
int newNumber = first * 2;
|
||||
newRow.add(newNumber);
|
||||
newScore += newNumber;
|
||||
thisRow.pop();
|
||||
} else {
|
||||
LOG.debug("Numbers don't match");
|
||||
newRow.add(first);
|
||||
}
|
||||
}
|
||||
newRow.addAll(thisRow);
|
||||
LOG.debug("Merged row: {}", newRow);
|
||||
|
||||
result[x] = new int[tiles[0].length];
|
||||
for (int y = 0; y < tiles[0].length; ++y) {
|
||||
if (newRow.isEmpty()) {
|
||||
result[x][y] = 0;
|
||||
} else {
|
||||
result[x][y] = newRow.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG.debug("After moves: {}", Arrays.deepToString(result));
|
||||
|
||||
// Un-reverse the board
|
||||
if (move == Move.DOWN || move == Move.RIGHT) {
|
||||
result = reverse(result);
|
||||
LOG.debug("After reverse: {}", Arrays.deepToString(result));
|
||||
}
|
||||
// Un-transpose the board
|
||||
if (move == Move.LEFT || move == Move.RIGHT) {
|
||||
result = transpose(result);
|
||||
LOG.debug("After transpose: {}", Arrays.deepToString(result));
|
||||
}
|
||||
return new Board(result, this.score + newScore);
|
||||
}
|
||||
|
||||
private static int[][] transpose(int[][] input) {
|
||||
int[][] result = new int[input.length][];
|
||||
|
||||
for (int x = 0; x < input.length; ++x) {
|
||||
result[x] = new int[input[0].length];
|
||||
for (int y = 0; y < input[0].length; ++y) {
|
||||
result[x][y] = input[y][x];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int[][] reverse(int[][] input) {
|
||||
int[][] result = new int[input.length][];
|
||||
|
||||
for (int x = 0; x < input.length; ++x) {
|
||||
result[x] = new int[input[0].length];
|
||||
for (int y = 0; y < input[0].length; ++y) {
|
||||
result[x][y] = input[x][input.length - y - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.deepToString(board);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Board board1 = (Board) o;
|
||||
return Arrays.deepEquals(board, board1.board);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.deepHashCode(board);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.algorithms.play2048;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
|
||||
public class Cell {
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
public Cell(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringJoiner(", ", Cell.class.getSimpleName() + "[", "]").add("x=" + x).add("y=" + y).toString();
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.baeldung.algorithms.play2048;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Computer {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Computer.class);
|
||||
|
||||
private final SecureRandom rng = new SecureRandom();
|
||||
|
||||
public Board makeMove(Board input) {
|
||||
List<Cell> emptyCells = input.emptyCells();
|
||||
LOG.info("Number of empty cells: {}", emptyCells.size());
|
||||
|
||||
double numberToPlace = rng.nextDouble();
|
||||
LOG.info("New number probability: {}", numberToPlace);
|
||||
|
||||
int indexToPlace = rng.nextInt(emptyCells.size());
|
||||
Cell cellToPlace = emptyCells.get(indexToPlace);
|
||||
LOG.info("Placing number into empty cell: {}", cellToPlace);
|
||||
|
||||
return input.placeTile(cellToPlace, numberToPlace >= 0.9 ? 4 : 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.baeldung.algorithms.play2048;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.math3.util.Pair;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Human {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Human.class);
|
||||
|
||||
public Board makeMove(Board input) {
|
||||
// For each move in MOVE
|
||||
// Generate board from move
|
||||
// Generate Score for Board
|
||||
// Return board with the best score
|
||||
//
|
||||
// Generate Score
|
||||
// If Depth Limit
|
||||
// Return Final Score
|
||||
// Total Score = 0
|
||||
// For every empty square in new board
|
||||
// Generate board with "2" in square
|
||||
// Calculate Score
|
||||
// Total Score += (Score * 0.9)
|
||||
// Generate board with "4" in square
|
||||
// Calculate Score
|
||||
// Total Score += (Score * 0.1)
|
||||
//
|
||||
// Calculate Score
|
||||
// For each move in MOVE
|
||||
// Generate board from move
|
||||
// Generate score for board
|
||||
// Return the best generated score
|
||||
|
||||
return Arrays.stream(Move.values())
|
||||
.parallel()
|
||||
.map(input::move)
|
||||
.filter(board -> !board.equals(input))
|
||||
.max(Comparator.comparingInt(board -> generateScore(board, 0)))
|
||||
.orElse(input);
|
||||
}
|
||||
|
||||
private int generateScore(Board board, int depth) {
|
||||
if (depth >= 3) {
|
||||
int finalScore = calculateFinalScore(board);
|
||||
LOG.debug("Final score for board {}: {}", board,finalScore);
|
||||
return finalScore;
|
||||
}
|
||||
|
||||
return board.emptyCells().stream()
|
||||
.parallel()
|
||||
.flatMap(cell -> Stream.of(new Pair<>(cell, 2), new Pair<>(cell, 4)))
|
||||
.mapToInt(move -> {
|
||||
LOG.debug("Simulating move {} at depth {}", move, depth);
|
||||
Board newBoard = board.placeTile(move.getFirst(), move.getSecond());
|
||||
int boardScore = calculateScore(newBoard, depth + 1);
|
||||
int calculatedScore = (int) (boardScore * (move.getSecond() == 2 ? 0.9 : 0.1));
|
||||
LOG.debug("Calculated score for board {} and move {} at depth {}: {}", newBoard, move, depth, calculatedScore);
|
||||
return calculatedScore;
|
||||
})
|
||||
.sum();
|
||||
}
|
||||
|
||||
private int calculateScore(Board board, int depth) {
|
||||
return Arrays.stream(Move.values())
|
||||
.parallel()
|
||||
.map(board::move)
|
||||
.filter(moved -> !moved.equals(board))
|
||||
.mapToInt(newBoard -> generateScore(newBoard, depth))
|
||||
.max()
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
private int calculateFinalScore(Board board) {
|
||||
List<List<Integer>> rowsToScore = new ArrayList<>();
|
||||
for (int i = 0; i < board.getSize(); ++i) {
|
||||
List<Integer> row = new ArrayList<>();
|
||||
List<Integer> col = new ArrayList<>();
|
||||
|
||||
for (int j = 0; j < board.getSize(); ++j) {
|
||||
row.add(board.getCell(new Cell(i, j)));
|
||||
col.add(board.getCell(new Cell(j, i)));
|
||||
}
|
||||
|
||||
rowsToScore.add(row);
|
||||
rowsToScore.add(col);
|
||||
}
|
||||
|
||||
return rowsToScore.stream()
|
||||
.parallel()
|
||||
.mapToInt(row -> {
|
||||
List<Integer> preMerged = row.stream()
|
||||
.filter(value -> value != 0)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
int numMerges = 0;
|
||||
int monotonicityLeft = 0;
|
||||
int monotonicityRight = 0;
|
||||
for (int i = 0; i < preMerged.size() - 1; ++i) {
|
||||
Integer first = preMerged.get(i);
|
||||
Integer second = preMerged.get(i + 1);
|
||||
if (first.equals(second)) {
|
||||
++numMerges;
|
||||
} else if (first > second) {
|
||||
monotonicityLeft += first - second;
|
||||
} else {
|
||||
monotonicityRight += second - first;
|
||||
}
|
||||
}
|
||||
|
||||
int score = 1000;
|
||||
score += 250 * row.stream().filter(value -> value == 0).count();
|
||||
score += 750 * numMerges;
|
||||
score -= 10 * row.stream().mapToInt(value -> value).sum();
|
||||
score -= 50 * Math.min(monotonicityLeft, monotonicityRight);
|
||||
return score;
|
||||
})
|
||||
.sum();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.algorithms.play2048;
|
||||
|
||||
public enum Move {
|
||||
UP,
|
||||
DOWN,
|
||||
LEFT,
|
||||
RIGHT
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.baeldung.algorithms.play2048;
|
||||
|
||||
public class Play2048 {
|
||||
private static final int SIZE = 3;
|
||||
private static final int INITIAL_NUMBERS = 2;
|
||||
|
||||
public static void main(String[] args) {
|
||||
// The board and players
|
||||
Board board = new Board(SIZE);
|
||||
Computer computer = new Computer();
|
||||
Human human = new Human();
|
||||
|
||||
// The computer has two moves first
|
||||
System.out.println("Setup");
|
||||
System.out.println("=====");
|
||||
for (int i = 0; i < INITIAL_NUMBERS; ++i) {
|
||||
board = computer.makeMove(board);
|
||||
}
|
||||
|
||||
printBoard(board);
|
||||
do {
|
||||
board = human.makeMove(board);
|
||||
System.out.println("Human move");
|
||||
System.out.println("==========");
|
||||
printBoard(board);
|
||||
|
||||
board = computer.makeMove(board);
|
||||
System.out.println("Computer move");
|
||||
System.out.println("=============");
|
||||
printBoard(board);
|
||||
} while (!board.emptyCells().isEmpty());
|
||||
|
||||
System.out.println("Final Score: " + board.getScore());
|
||||
|
||||
}
|
||||
|
||||
private static void printBoard(Board board) {
|
||||
StringBuilder topLines = new StringBuilder();
|
||||
StringBuilder midLines = new StringBuilder();
|
||||
for (int x = 0; x < board.getSize(); ++x) {
|
||||
topLines.append("+--------");
|
||||
midLines.append("| ");
|
||||
}
|
||||
topLines.append("+");
|
||||
midLines.append("|");
|
||||
|
||||
|
||||
for (int y = 0; y < board.getSize(); ++y) {
|
||||
System.out.println(topLines);
|
||||
System.out.println(midLines);
|
||||
for (int x = 0; x < board.getSize(); ++x) {
|
||||
Cell cell = new Cell(x, y);
|
||||
System.out.print("|");
|
||||
if (board.isEmpty(cell)) {
|
||||
System.out.print(" ");
|
||||
} else {
|
||||
StringBuilder output = new StringBuilder(Integer.toString(board.getCell(cell)));
|
||||
while (output.length() < 8) {
|
||||
output.append(" ");
|
||||
if (output.length() < 8) {
|
||||
output.insert(0, " ");
|
||||
}
|
||||
}
|
||||
System.out.print(output);
|
||||
}
|
||||
}
|
||||
System.out.println("|");
|
||||
System.out.println(midLines);
|
||||
}
|
||||
System.out.println(topLines);
|
||||
System.out.println("Score: " + board.getScore());
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -5,21 +5,21 @@ import static com.baeldung.algorithms.quicksort.SortingUtils.swap;
|
||||
|
||||
public class DutchNationalFlagPartioning {
|
||||
|
||||
public static Partition partition(int[] a, int begin, int end) {
|
||||
public static Partition partition(int[] input, int begin, int end) {
|
||||
int lt = begin, current = begin, gt = end;
|
||||
int partitioningValue = a[begin];
|
||||
int partitioningValue = input[begin];
|
||||
|
||||
while (current <= gt) {
|
||||
int compareCurrent = compare(a[current], partitioningValue);
|
||||
int compareCurrent = compare(input[current], partitioningValue);
|
||||
switch (compareCurrent) {
|
||||
case -1:
|
||||
swap(a, current++, lt++);
|
||||
swap(input, current++, lt++);
|
||||
break;
|
||||
case 0:
|
||||
current++;
|
||||
break;
|
||||
case 1:
|
||||
swap(a, current, gt--);
|
||||
swap(input, current, gt--);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.determinedatatype
|
||||
|
||||
class Person {
|
||||
|
||||
private int ageAsInt
|
||||
private Double ageAsDouble
|
||||
private String ageAsString
|
||||
|
||||
Person() {}
|
||||
Person(int ageAsInt) { this.ageAsInt = ageAsInt}
|
||||
Person(Double ageAsDouble) { this.ageAsDouble = ageAsDouble}
|
||||
Person(String ageAsString) { this.ageAsString = ageAsString}
|
||||
}
|
||||
class Student extends Person {}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.baeldung.determinedatatype
|
||||
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import com.baeldung.determinedatatype.Person
|
||||
|
||||
public class PersonTest {
|
||||
|
||||
@Test
|
||||
public void givenWhenParameterTypeIsInteger_thenReturnTrue() {
|
||||
Person personObj = new Person(10)
|
||||
Assert.assertTrue(personObj.ageAsInt instanceof Integer)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenWhenParameterTypeIsDouble_thenReturnTrue() {
|
||||
Person personObj = new Person(10.0)
|
||||
Assert.assertTrue((personObj.ageAsDouble).getClass() == Double)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenWhenParameterTypeIsString_thenReturnTrue() {
|
||||
Person personObj = new Person("10 years")
|
||||
Assert.assertTrue(personObj.ageAsString.class == String)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenClassName_WhenParameterIsInteger_thenReturnTrue() {
|
||||
Assert.assertTrue(Person.class.getDeclaredField('ageAsInt').type == int.class)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenWhenObjectIsInstanceOfType_thenReturnTrue() {
|
||||
Person personObj = new Person()
|
||||
Assert.assertTrue(personObj instanceof Person)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenWhenInstanceIsOfSubtype_thenReturnTrue() {
|
||||
Student studentObj = new Student()
|
||||
Assert.assertTrue(studentObj in Person)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGroovyList_WhenFindClassName_thenReturnTrue() {
|
||||
def ageList = ['ageAsString','ageAsDouble', 10]
|
||||
Assert.assertTrue(ageList.class == ArrayList)
|
||||
Assert.assertTrue(ageList.getClass() == ArrayList)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGrooyMap_WhenFindClassName_thenReturnTrue() {
|
||||
def ageMap = [ageAsString: '10 years', ageAsDouble: 10.0]
|
||||
Assert.assertFalse(ageMap.class == LinkedHashMap)
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,4 @@ This module contains articles about Java 14.
|
||||
- [Pattern Matching for instanceof in Java 14](https://www.baeldung.com/java-pattern-matching-instanceof)
|
||||
- [Helpful NullPointerExceptions in Java 14](https://www.baeldung.com/java-14-nullpointerexception)
|
||||
- [Foreign Memory Access API in Java 14](https://www.baeldung.com/java-foreign-memory-access)
|
||||
- [Java 14 Record Keyword](https://www.baeldung.com/java-record-keyword)
|
||||
|
||||
@@ -5,7 +5,7 @@ This module contains articles about the improvements to core Java features intro
|
||||
### Relevant Articles:
|
||||
|
||||
- [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors)
|
||||
- [Java 9 Convenience Factory Methods for Collections](https://www.baeldung.com/java-9-collections-factory-methods)
|
||||
- [Java Convenience Factory Methods for Collections](https://www.baeldung.com/java-9-collections-factory-methods)
|
||||
- [Java 9 Stream API Improvements](https://www.baeldung.com/java-9-stream-api)
|
||||
- [Java 9 java.util.Objects Additions](https://www.baeldung.com/java-9-objects-new)
|
||||
- [Java 9 CompletableFuture API Improvements](https://www.baeldung.com/java-9-completablefuture)
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class JavaArraysToStringUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenInstanceOfArray_whenTryingToConvertToString_thenNameOfClassIsShown() {
|
||||
Object[] arrayOfObjects = { "John", 2, true };
|
||||
assertTrue(arrayOfObjects.toString().startsWith("[Ljava.lang.Object;"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInstanceOfArray_whenUsingArraysToStringToConvert_thenValueOfObjectsAreShown() {
|
||||
Object[] arrayOfObjects = { "John", 2, true };
|
||||
assertEquals(Arrays.toString(arrayOfObjects), "[John, 2, true]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInstanceOfDeepArray_whenUsingArraysDeepToStringToConvert_thenValueOfInnerObjectsAreShown() {
|
||||
Object[] innerArray = { "We", "Are", "Inside" };
|
||||
Object[] arrayOfObjects = { "John", 2, innerArray };
|
||||
assertEquals(Arrays.deepToString(arrayOfObjects), "[John, 2, [We, Are, Inside]]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInstanceOfDeepArray_whenUsingStreamsToConvert_thenValueOfObjectsAreShown() {
|
||||
Object[] arrayOfObjects = { "John", 2, true };
|
||||
List<String> listOfString = Stream.of(arrayOfObjects)
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(listOfString.toString(), "[John, 2, true]");
|
||||
}
|
||||
}
|
||||
@@ -13,4 +13,5 @@ This module contains articles about advanced topics about multithreading with co
|
||||
- [Java Thread Deadlock and Livelock](https://www.baeldung.com/java-deadlock-livelock)
|
||||
- [Guide to AtomicStampedReference in Java](https://www.baeldung.com/java-atomicstampedreference)
|
||||
- [The ABA Problem in Concurrency](https://www.baeldung.com/cs/aba-concurrency)
|
||||
- [Introduction to Lock-Free Data Structures](https://www.baeldung.com/lock-free-programming)
|
||||
- [[<-- previous]](/core-java-modules/core-java-concurrency-advanced-2)
|
||||
|
||||
@@ -13,3 +13,4 @@ This module contains articles about concurrent Java collections
|
||||
- [Guide to the Java TransferQueue](http://www.baeldung.com/java-transfer-queue)
|
||||
- [Guide to the ConcurrentSkipListMap](http://www.baeldung.com/java-concurrent-skip-list-map)
|
||||
- [Guide to CopyOnWriteArrayList](http://www.baeldung.com/java-copy-on-write-arraylist)
|
||||
- [LinkedBlockingQueue vs ConcurrentLinkedQueue](https://www.baeldung.com/java-queue-linkedblocking-concurrentlinked)
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package com.baeldung.exceptions;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
||||
|
||||
public class TooManyOpenFilesExceptionLiveTest {
|
||||
|
||||
private File tempFile;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws IOException {
|
||||
tempFile = File.createTempFile("testForException", "tmp");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
System.gc();
|
||||
tempFile.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNotClosingResoures_thenIOExceptionShouldBeThrown() {
|
||||
try {
|
||||
for (int x = 0; x < 1000000; x++) {
|
||||
FileInputStream leakyHandle = new FileInputStream(tempFile);
|
||||
}
|
||||
Assertions.fail("Method Should Have Failed");
|
||||
} catch (IOException e) {
|
||||
assertTrue(e.getMessage().toLowerCase().contains("too many open files"));
|
||||
} catch (Exception e) {
|
||||
Assertions.fail("Unexpected exception");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenClosingResoures_thenIOExceptionShouldNotBeThrown() {
|
||||
try {
|
||||
for (int x = 0; x < 1000000; x++) {
|
||||
FileInputStream nonLeakyHandle = null;
|
||||
try {
|
||||
nonLeakyHandle = new FileInputStream(tempFile);
|
||||
} finally {
|
||||
if (nonLeakyHandle != null) {
|
||||
nonLeakyHandle.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
assertFalse(e.getMessage().toLowerCase().contains("too many open files"));
|
||||
Assertions.fail("Method Should Not Have Failed");
|
||||
} catch (Exception e) {
|
||||
Assertions.fail("Unexpected exception");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingTryWithResoures_thenIOExceptionShouldNotBeThrown() {
|
||||
try {
|
||||
for (int x = 0; x < 1000000; x++) {
|
||||
try (FileInputStream nonLeakyHandle = new FileInputStream(tempFile)) {
|
||||
//Do something with the file
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
assertFalse(e.getMessage().toLowerCase().contains("too many open files"));
|
||||
Assertions.fail("Method Should Not Have Failed");
|
||||
} catch (Exception e) {
|
||||
Assertions.fail("Unexpected exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,14 +51,37 @@
|
||||
<scope>system</scope>
|
||||
<systemPath>${java.home}/../lib/tools.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<version>${asm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-util</artifactId>
|
||||
<version>${asm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.bcel</groupId>
|
||||
<artifactId>bcel</artifactId>
|
||||
<version>${bcel.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jol</groupId>
|
||||
<artifactId>jol-core</artifactId>
|
||||
<version>${jol-core.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<assertj.version>3.6.1</assertj.version>
|
||||
<!-- instrumentation -->
|
||||
<javaassist.version>3.21.0-GA</javaassist.version>
|
||||
<javaassist.version>3.27.0-GA</javaassist.version>
|
||||
<esapi.version>2.1.0.1</esapi.version>
|
||||
<sun.tools.version>1.8.0</sun.tools.version>
|
||||
<jol-core.version>0.10</jol-core.version>
|
||||
<asm.version>8.0.1</asm.version>
|
||||
<bcel.version>6.5.0</bcel.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.boolsize;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openjdk.jol.info.ClassLayout;
|
||||
import org.openjdk.jol.vm.VM;
|
||||
|
||||
public class BooleanSizeUnitTest {
|
||||
|
||||
@Test
|
||||
public void printingTheVMDetails() {
|
||||
System.out.println(VM.current().details());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void printingTheBoolWrapper() {
|
||||
System.out.println(ClassLayout.parseClass(BooleanWrapper.class).toPrintable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void printingTheBoolArray() {
|
||||
boolean[] value = new boolean[3];
|
||||
|
||||
System.out.println(ClassLayout.parseInstance(value).toPrintable());
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.baeldung.boolsize;
|
||||
|
||||
class BooleanWrapper {
|
||||
private boolean value;
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package com.baeldung.bytecode;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.apache.bcel.Repository;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.junit.Test;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.util.TraceClassVisitor;
|
||||
import javassist.ClassPool;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.bytecode.ClassFile;
|
||||
|
||||
public class ViewBytecodeUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenUsingASM_thenReadBytecode() throws IOException {
|
||||
ClassReader reader = new ClassReader("java.lang.Object");
|
||||
StringWriter sw = new StringWriter();
|
||||
TraceClassVisitor tcv = new TraceClassVisitor(new PrintWriter(sw));
|
||||
reader.accept(tcv, 0);
|
||||
|
||||
assertTrue(sw.toString().contains("public class java/lang/Object"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingBCEL_thenReadBytecode() throws ClassNotFoundException {
|
||||
JavaClass objectClazz = Repository.lookupClass("java.lang.Object");
|
||||
|
||||
assertEquals(objectClazz.getClassName(), "java.lang.Object");
|
||||
assertEquals(objectClazz.getMethods().length, 14);
|
||||
assertTrue(objectClazz.toString().contains("public class java.lang.Object"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingJavassist_thenReadBytecode() throws NotFoundException {
|
||||
ClassPool cp = ClassPool.getDefault();
|
||||
ClassFile cf = cp.get("java.lang.Object").getClassFile();
|
||||
|
||||
assertEquals(cf.getName(), "java.lang.Object");
|
||||
assertEquals(cf.getMethods().size(), 14);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
- [Java 8 Math New Methods](https://www.baeldung.com/java-8-math)
|
||||
- [Java 8 Unsigned Arithmetic Support](https://www.baeldung.com/java-unsigned-arithmetic)
|
||||
- [How to Separate Double into Integer and Decimal Parts](https://www.baeldung.com/java-separate-double-into-integer-decimal-parts)
|
||||
- [The strictfp Keyword in Java](https://www.baeldung.com/java-strictfp)
|
||||
- [Basic Calculator in Java](https://www.baeldung.com/java-basic-calculator)
|
||||
- [Overflow and Underflow in Java](https://www.baeldung.com/java-overflow-underflow)
|
||||
- [Obtaining a Power Set of a Set in Java](https://www.baeldung.com/java-power-set-of-a-set)
|
||||
|
||||
@@ -7,3 +7,6 @@ This module contains articles about types in Java
|
||||
- [Guide to the this Java Keyword](https://www.baeldung.com/java-this)
|
||||
- [Nested Classes in Java](https://www.baeldung.com/java-nested-classes)
|
||||
- [Marker Interfaces in Java](https://www.baeldung.com/java-marker-interfaces)
|
||||
- [Iterating Over Enum Values in Java](https://www.baeldung.com/java-enum-iteration)
|
||||
- [Attaching Values to Java Enum](https://www.baeldung.com/java-enum-values)
|
||||
- [A Guide to Java Enums](https://www.baeldung.com/a-guide-to-java-enums)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user