Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -43,3 +43,4 @@ spring-call-getters-using-reflection/.mvn/wrapper/maven-wrapper.properties
|
||||
spring-check-if-a-property-is-null/.mvn/wrapper/maven-wrapper.properties
|
||||
*.springBeans
|
||||
|
||||
20171220-JMeter.csv
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.baeldung.algorithms.maze.solver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class BFSMazeSolver {
|
||||
private static final int[][] DIRECTIONS = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
|
||||
|
||||
public List<Coordinate> solve(Maze maze) {
|
||||
LinkedList<Coordinate> nextToVisit = new LinkedList<>();
|
||||
Coordinate start = maze.getEntry();
|
||||
nextToVisit.add(start);
|
||||
|
||||
while (!nextToVisit.isEmpty()) {
|
||||
Coordinate cur = nextToVisit.remove();
|
||||
|
||||
if (!maze.isValidLocation(cur.getX(), cur.getY()) || maze.isExplored(cur.getX(), cur.getY())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (maze.isWall(cur.getX(), cur.getY())) {
|
||||
maze.setVisited(cur.getX(), cur.getY(), true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (maze.isExit(cur.getX(), cur.getY())) {
|
||||
return backtrackPath(cur);
|
||||
}
|
||||
|
||||
for (int[] direction : DIRECTIONS) {
|
||||
Coordinate coordinate = new Coordinate(cur.getX() + direction[0], cur.getY() + direction[1], cur);
|
||||
nextToVisit.add(coordinate);
|
||||
maze.setVisited(cur.getX(), cur.getY(), true);
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<Coordinate> backtrackPath(Coordinate cur) {
|
||||
List<Coordinate> path = new ArrayList<>();
|
||||
Coordinate iter = cur;
|
||||
|
||||
while (iter != null) {
|
||||
path.add(iter);
|
||||
iter = iter.parent;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.algorithms.maze.solver;
|
||||
|
||||
public class Coordinate {
|
||||
int x;
|
||||
int y;
|
||||
Coordinate parent;
|
||||
|
||||
public Coordinate(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.parent = null;
|
||||
}
|
||||
|
||||
public Coordinate(int x, int y, Coordinate parent) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
Coordinate getParent() {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.baeldung.algorithms.maze.solver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class DFSMazeSolver {
|
||||
private static final int[][] DIRECTIONS = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
|
||||
|
||||
public List<Coordinate> solve(Maze maze) {
|
||||
List<Coordinate> path = new ArrayList<>();
|
||||
if (explore(maze, maze.getEntry()
|
||||
.getX(),
|
||||
maze.getEntry()
|
||||
.getY(),
|
||||
path)) {
|
||||
return path;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private boolean explore(Maze maze, int row, int col, List<Coordinate> path) {
|
||||
if (!maze.isValidLocation(row, col) || maze.isWall(row, col) || maze.isExplored(row, col)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
path.add(new Coordinate(row, col));
|
||||
maze.setVisited(row, col, true);
|
||||
|
||||
if (maze.isExit(row, col)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int[] direction : DIRECTIONS) {
|
||||
Coordinate coordinate = getNextCoordinate(row, col, direction[0], direction[1]);
|
||||
if (explore(maze, coordinate.getX(), coordinate.getY(), path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
path.remove(path.size() - 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
private Coordinate getNextCoordinate(int row, int col, int i, int j) {
|
||||
return new Coordinate(row + i, col + j);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.baeldung.algorithms.maze.solver;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Maze {
|
||||
private static final int ROAD = 0;
|
||||
private static final int WALL = 1;
|
||||
private static final int START = 2;
|
||||
private static final int EXIT = 3;
|
||||
private static final int PATH = 4;
|
||||
|
||||
private int[][] maze;
|
||||
private boolean[][] visited;
|
||||
private Coordinate start;
|
||||
private Coordinate end;
|
||||
|
||||
public Maze(File maze) throws FileNotFoundException {
|
||||
String fileText = "";
|
||||
try (Scanner input = new Scanner(maze)) {
|
||||
while (input.hasNextLine()) {
|
||||
fileText += input.nextLine() + "\n";
|
||||
}
|
||||
}
|
||||
initializeMaze(fileText);
|
||||
}
|
||||
|
||||
private void initializeMaze(String text) {
|
||||
if (text == null || (text = text.trim()).length() == 0) {
|
||||
throw new IllegalArgumentException("empty lines data");
|
||||
}
|
||||
|
||||
String[] lines = text.split("[\r]?\n");
|
||||
maze = new int[lines.length][lines[0].length()];
|
||||
visited = new boolean[lines.length][lines[0].length()];
|
||||
|
||||
for (int row = 0; row < getHeight(); row++) {
|
||||
if (lines[row].length() != getWidth()) {
|
||||
throw new IllegalArgumentException("line " + (row + 1) + " wrong length (was " + lines[row].length() + " but should be " + getWidth() + ")");
|
||||
}
|
||||
|
||||
for (int col = 0; col < getWidth(); col++) {
|
||||
if (lines[row].charAt(col) == '#')
|
||||
maze[row][col] = WALL;
|
||||
else if (lines[row].charAt(col) == 'S') {
|
||||
maze[row][col] = START;
|
||||
start = new Coordinate(row, col);
|
||||
} else if (lines[row].charAt(col) == 'E') {
|
||||
maze[row][col] = EXIT;
|
||||
end = new Coordinate(row, col);
|
||||
} else
|
||||
maze[row][col] = ROAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return maze.length;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return maze[0].length;
|
||||
}
|
||||
|
||||
public Coordinate getEntry() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public Coordinate getExit() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public boolean isExit(int x, int y) {
|
||||
return x == end.getX() && y == end.getY();
|
||||
}
|
||||
|
||||
public boolean isStart(int x, int y) {
|
||||
return x == start.getX() && y == start.getY();
|
||||
}
|
||||
|
||||
public boolean isExplored(int row, int col) {
|
||||
return visited[row][col];
|
||||
}
|
||||
|
||||
public boolean isWall(int row, int col) {
|
||||
return maze[row][col] == WALL;
|
||||
}
|
||||
|
||||
public void setVisited(int row, int col, boolean value) {
|
||||
visited[row][col] = value;
|
||||
}
|
||||
|
||||
public boolean isValidLocation(int row, int col) {
|
||||
if (row < 0 || row >= getHeight() || col < 0 || col >= getWidth()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void printPath(List<Coordinate> path) {
|
||||
int[][] tempMaze = Arrays.stream(maze)
|
||||
.map(int[]::clone)
|
||||
.toArray(int[][]::new);
|
||||
for (Coordinate coordinate : path) {
|
||||
if (isStart(coordinate.getX(), coordinate.getY()) || isExit(coordinate.getX(), coordinate.getY())) {
|
||||
continue;
|
||||
}
|
||||
tempMaze[coordinate.getX()][coordinate.getY()] = PATH;
|
||||
}
|
||||
System.out.println(toString(tempMaze));
|
||||
}
|
||||
|
||||
public String toString(int[][] maze) {
|
||||
StringBuilder result = new StringBuilder(getWidth() * (getHeight() + 1));
|
||||
for (int row = 0; row < getHeight(); row++) {
|
||||
for (int col = 0; col < getWidth(); col++) {
|
||||
if (maze[row][col] == ROAD) {
|
||||
result.append(' ');
|
||||
} else if (maze[row][col] == WALL) {
|
||||
result.append('#');
|
||||
} else if (maze[row][col] == START) {
|
||||
result.append('S');
|
||||
} else if (maze[row][col] == EXIT) {
|
||||
result.append('E');
|
||||
} else {
|
||||
result.append('.');
|
||||
}
|
||||
}
|
||||
result.append('\n');
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
for (int i = 0; i < visited.length; i++)
|
||||
Arrays.fill(visited[i], false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.baeldung.algorithms.maze.solver;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
public class MazeDriver {
|
||||
public static void main(String[] args) throws Exception {
|
||||
File maze1 = new File("src/main/resources/maze/maze1.txt");
|
||||
File maze2 = new File("src/main/resources/maze/maze2.txt");
|
||||
|
||||
execute(maze1);
|
||||
execute(maze2);
|
||||
}
|
||||
|
||||
private static void execute(File file) throws Exception {
|
||||
Maze maze = new Maze(file);
|
||||
dfs(maze);
|
||||
bfs(maze);
|
||||
}
|
||||
|
||||
private static void bfs(Maze maze) {
|
||||
BFSMazeSolver bfs = new BFSMazeSolver();
|
||||
List<Coordinate> path = bfs.solve(maze);
|
||||
maze.printPath(path);
|
||||
maze.reset();
|
||||
}
|
||||
|
||||
private static void dfs(Maze maze) {
|
||||
DFSMazeSolver dfs = new DFSMazeSolver();
|
||||
List<Coordinate> path = dfs.solve(maze);
|
||||
maze.printPath(path);
|
||||
maze.reset();
|
||||
}
|
||||
}
|
||||
+25
-25
@@ -40,15 +40,15 @@ public class BacktrackingAlgorithm {
|
||||
}
|
||||
|
||||
private boolean solve(int[][] board) {
|
||||
for (int r = BOARD_START_INDEX; r < BOARD_SIZE; r++) {
|
||||
for (int c = BOARD_START_INDEX; c < BOARD_SIZE; c++) {
|
||||
if (board[r][c] == NO_VALUE) {
|
||||
for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) {
|
||||
for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) {
|
||||
if (board[row][column] == NO_VALUE) {
|
||||
for (int k = MIN_VALUE; k <= MAX_VALUE; k++) {
|
||||
board[r][c] = k;
|
||||
if (isValid(board, r, c) && solve(board)) {
|
||||
board[row][column] = k;
|
||||
if (isValid(board, row, column) && solve(board)) {
|
||||
return true;
|
||||
}
|
||||
board[r][c] = NO_VALUE;
|
||||
board[row][column] = NO_VALUE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -57,48 +57,48 @@ public class BacktrackingAlgorithm {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValid(int[][] board, int r, int c) {
|
||||
return rowConstraint(board, r) &&
|
||||
columnConstraint(board, c) &&
|
||||
subsectionConstraint(board, r, c);
|
||||
private boolean isValid(int[][] board, int row, int column) {
|
||||
return rowConstraint(board, row) &&
|
||||
columnConstraint(board, column) &&
|
||||
subsectionConstraint(board, row, column);
|
||||
}
|
||||
|
||||
private boolean subsectionConstraint(int[][] board, int r, int c) {
|
||||
private boolean subsectionConstraint(int[][] board, int row, int column) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
int subsectionRowStart = (r / SUBSECTION_SIZE) * SUBSECTION_SIZE;
|
||||
int subsectionRowStart = (row / SUBSECTION_SIZE) * SUBSECTION_SIZE;
|
||||
int subsectionRowEnd = subsectionRowStart + SUBSECTION_SIZE;
|
||||
|
||||
int subsectionColumnStart = (c / SUBSECTION_SIZE) * SUBSECTION_SIZE;
|
||||
int subsectionColumnStart = (column / SUBSECTION_SIZE) * SUBSECTION_SIZE;
|
||||
int subsectionColumnEnd = subsectionColumnStart + SUBSECTION_SIZE;
|
||||
|
||||
for (int i = subsectionRowStart; i < subsectionRowEnd; i++) {
|
||||
for (int j = subsectionColumnStart; j < subsectionColumnEnd; j++) {
|
||||
if (!checkConstraint(board, i, constraint, j)) return false;
|
||||
for (int r = subsectionRowStart; r < subsectionRowEnd; r++) {
|
||||
for (int c = subsectionColumnStart; c < subsectionColumnEnd; c++) {
|
||||
if (!checkConstraint(board, r, constraint, c)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean columnConstraint(int[][] board, int c) {
|
||||
private boolean columnConstraint(int[][] board, int column) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
return IntStream.range(BOARD_START_INDEX, BOARD_SIZE)
|
||||
.allMatch(i -> checkConstraint(board, i, constraint, c));
|
||||
.allMatch(row -> checkConstraint(board, row, constraint, column));
|
||||
}
|
||||
|
||||
private boolean rowConstraint(int[][] board, int r) {
|
||||
private boolean rowConstraint(int[][] board, int row) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
return IntStream.range(BOARD_START_INDEX, BOARD_SIZE)
|
||||
.allMatch(i -> checkConstraint(board, r, constraint, i));
|
||||
.allMatch(column -> checkConstraint(board, row, constraint, column));
|
||||
}
|
||||
|
||||
private boolean checkConstraint(int[][] board, int r, boolean[] constraint, int c) {
|
||||
if (board[r][c] != NO_VALUE) {
|
||||
if (!constraint[board[r][c] - 1]) {
|
||||
constraint[board[r][c] - 1] = true;
|
||||
private boolean checkConstraint(int[][] board, int row, boolean[] constraint, int column) {
|
||||
if (board[row][column] != NO_VALUE) {
|
||||
if (!constraint[board[row][column] - 1]) {
|
||||
constraint[board[row][column] - 1] = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,10 +120,10 @@ public class DancingLinks {
|
||||
}
|
||||
|
||||
private static void printSolution(int[][] result) {
|
||||
int N = result.length;
|
||||
int size = result.length;
|
||||
for (int[] aResult : result) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
for (int j = 0; j < N; j++) {
|
||||
for (int j = 0; j < size; j++) {
|
||||
ret.append(aResult[j]).append(" ");
|
||||
}
|
||||
System.out.println(ret);
|
||||
|
||||
+60
-47
@@ -34,75 +34,88 @@ public class DancingLinksAlgorithm {
|
||||
dlx.runSolver();
|
||||
}
|
||||
|
||||
private int getIndex(int row, int col, int num) {
|
||||
return (row - 1) * BOARD_SIZE * BOARD_SIZE + (col - 1) * BOARD_SIZE + (num - 1);
|
||||
private int getIndex(int row, int column, int num) {
|
||||
return (row - 1) * BOARD_SIZE * BOARD_SIZE + (column - 1) * BOARD_SIZE + (num - 1);
|
||||
}
|
||||
|
||||
private boolean[][] createExactCoverBoard() {
|
||||
boolean[][] R = new boolean[BOARD_SIZE * BOARD_SIZE * MAX_VALUE][BOARD_SIZE * BOARD_SIZE * CONSTRAINTS];
|
||||
boolean[][] coverBoard = new boolean[BOARD_SIZE * BOARD_SIZE * MAX_VALUE][BOARD_SIZE * BOARD_SIZE * CONSTRAINTS];
|
||||
|
||||
int hBase = 0;
|
||||
hBase = checkCellConstraint(coverBoard, hBase);
|
||||
hBase = checkRowConstraint(coverBoard, hBase);
|
||||
hBase = checkColumnConstraint(coverBoard, hBase);
|
||||
checkSubsectionConstraint(coverBoard, hBase);
|
||||
|
||||
return coverBoard;
|
||||
}
|
||||
|
||||
// Cell constraint.
|
||||
for (int r = COVER_START_INDEX; r <= BOARD_SIZE; r++) {
|
||||
for (int c = COVER_START_INDEX; c <= BOARD_SIZE; c++, hBase++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++) {
|
||||
int index = getIndex(r, c, n);
|
||||
R[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Row constrain.
|
||||
for (int r = COVER_START_INDEX; r <= BOARD_SIZE; r++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
|
||||
for (int c1 = COVER_START_INDEX; c1 <= BOARD_SIZE; c1++) {
|
||||
int index = getIndex(r, c1, n);
|
||||
R[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Column constraint.
|
||||
for (int c = COVER_START_INDEX; c <= BOARD_SIZE; c++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
|
||||
for (int r1 = COVER_START_INDEX; r1 <= BOARD_SIZE; r1++) {
|
||||
int index = getIndex(r1, c, n);
|
||||
R[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Subsection constraint
|
||||
for (int br = COVER_START_INDEX; br <= BOARD_SIZE; br += SUBSECTION_SIZE) {
|
||||
for (int bc = COVER_START_INDEX; bc <= BOARD_SIZE; bc += SUBSECTION_SIZE) {
|
||||
private int checkSubsectionConstraint(boolean[][] coverBoard, int hBase) {
|
||||
for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row += SUBSECTION_SIZE) {
|
||||
for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column += SUBSECTION_SIZE) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
|
||||
for (int rDelta = 0; rDelta < SUBSECTION_SIZE; rDelta++) {
|
||||
for (int cDelta = 0; cDelta < SUBSECTION_SIZE; cDelta++) {
|
||||
int index = getIndex(br + rDelta, bc + cDelta, n);
|
||||
R[index][hBase] = true;
|
||||
for (int rowDelta = 0; rowDelta < SUBSECTION_SIZE; rowDelta++) {
|
||||
for (int columnDelta = 0; columnDelta < SUBSECTION_SIZE; columnDelta++) {
|
||||
int index = getIndex(row + rowDelta, column + columnDelta, n);
|
||||
coverBoard[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return R;
|
||||
return hBase;
|
||||
}
|
||||
|
||||
private int checkColumnConstraint(boolean[][] coverBoard, int hBase) {
|
||||
for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
|
||||
for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
|
||||
int index = getIndex(row, column, n);
|
||||
coverBoard[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hBase;
|
||||
}
|
||||
|
||||
private int checkRowConstraint(boolean[][] coverBoard, int hBase) {
|
||||
for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
|
||||
for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++) {
|
||||
int index = getIndex(row, column, n);
|
||||
coverBoard[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hBase;
|
||||
}
|
||||
|
||||
private int checkCellConstraint(boolean[][] coverBoard, int hBase) {
|
||||
for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
|
||||
for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++, hBase++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++) {
|
||||
int index = getIndex(row, column, n);
|
||||
coverBoard[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hBase;
|
||||
}
|
||||
|
||||
private boolean[][] initializeExactCoverBoard(int[][] board) {
|
||||
boolean[][] R = createExactCoverBoard();
|
||||
for (int i = COVER_START_INDEX; i <= BOARD_SIZE; i++) {
|
||||
for (int j = COVER_START_INDEX; j <= BOARD_SIZE; j++) {
|
||||
int n = board[i - 1][j - 1];
|
||||
boolean[][] coverBoard = createExactCoverBoard();
|
||||
for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
|
||||
for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++) {
|
||||
int n = board[row - 1][column - 1];
|
||||
if (n != NO_VALUE) {
|
||||
for (int num = MIN_VALUE; num <= MAX_VALUE; num++) {
|
||||
if (num != n) {
|
||||
Arrays.fill(R[getIndex(i, j, num)], false);
|
||||
Arrays.fill(coverBoard[getIndex(row, column, num)], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return R;
|
||||
return coverBoard;
|
||||
}
|
||||
}
|
||||
@@ -4,21 +4,21 @@ class DancingNode {
|
||||
DancingNode L, R, U, D;
|
||||
ColumnNode C;
|
||||
|
||||
DancingNode hookDown(DancingNode n1) {
|
||||
assert (this.C == n1.C);
|
||||
n1.D = this.D;
|
||||
n1.D.U = n1;
|
||||
n1.U = this;
|
||||
this.D = n1;
|
||||
return n1;
|
||||
DancingNode hookDown(DancingNode node) {
|
||||
assert (this.C == node.C);
|
||||
node.D = this.D;
|
||||
node.D.U = node;
|
||||
node.U = this;
|
||||
this.D = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
DancingNode hookRight(DancingNode n1) {
|
||||
n1.R = this.R;
|
||||
n1.R.L = n1;
|
||||
n1.L = this;
|
||||
this.R = n1;
|
||||
return n1;
|
||||
DancingNode hookRight(DancingNode node) {
|
||||
node.R = this.R;
|
||||
node.R.L = node;
|
||||
node.L = this;
|
||||
this.R = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
void unlinkLR() {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
S ########
|
||||
# #
|
||||
# ### ## #
|
||||
# # # #
|
||||
# # # # #
|
||||
# ## #####
|
||||
# # #
|
||||
# # # # #
|
||||
##### ####
|
||||
# # E
|
||||
# # # #
|
||||
##########
|
||||
@@ -0,0 +1,22 @@
|
||||
S ##########################
|
||||
# # # #
|
||||
# # #### ############### #
|
||||
# # # # # #
|
||||
# # #### # # ###############
|
||||
# # # # # # #
|
||||
# # # #### ### ########### #
|
||||
# # # # # #
|
||||
# ################## #
|
||||
######### # # # # #
|
||||
# # #### # ####### # #
|
||||
# # ### ### # # # # #
|
||||
# # ## # ##### # #
|
||||
##### ####### # # # # #
|
||||
# # ## ## #### # #
|
||||
# ##### ####### # #
|
||||
# # ############
|
||||
####### ######### # #
|
||||
# # ######## #
|
||||
# ####### ###### ## # E
|
||||
# # # ## #
|
||||
############################
|
||||
@@ -0,0 +1,114 @@
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>checker-plugin</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>checker-plugin</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<!-- https://checkerframework.org/manual/#maven -->
|
||||
|
||||
<properties>
|
||||
<!-- These properties will be set by the Maven Dependency plugin -->
|
||||
<annotatedJdk>${org.checkerframework:jdk8:jar}</annotatedJdk>
|
||||
<!-- Uncomment to use the Type Annotations compiler. -->
|
||||
<!--
|
||||
<typeAnnotationsJavac>${org.checkerframework:compiler:jar}</typeAnnotationsJavac>
|
||||
-->
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
|
||||
<!-- Annotations from the Checker Framework: nullness, interning, locking, ... -->
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>jdk8</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
<!-- The Type Annotations compiler. Uncomment if using annotations in comments. -->
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>compiler</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<!-- This plugin will set properties values using dependency information -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<!--
|
||||
Goal that sets a property pointing to the artifact file for each project dependency.
|
||||
For each dependency (direct and transitive) a project property will be set which
|
||||
follows the:
|
||||
|
||||
groupId:artifactId:type:[classifier]
|
||||
|
||||
form and contains the path to the resolved artifact. -->
|
||||
<goal>properties</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<!-- Uncomment the following line to use the type annotations compiler. -->
|
||||
<!-- <fork>true</fork> -->
|
||||
<compilerArguments>
|
||||
<Xmaxerrs>10000</Xmaxerrs>
|
||||
<Xmaxwarns>10000</Xmaxwarns>
|
||||
</compilerArguments>
|
||||
<annotationProcessors>
|
||||
<!-- Add all the checkers you want to enable here -->
|
||||
<annotationProcessor>org.checkerframework.checker.nullness.NullnessChecker</annotationProcessor>
|
||||
<annotationProcessor>org.checkerframework.checker.interning.InterningChecker</annotationProcessor>
|
||||
<annotationProcessor>org.checkerframework.checker.fenum.FenumChecker</annotationProcessor>
|
||||
<annotationProcessor>org.checkerframework.checker.formatter.FormatterChecker</annotationProcessor>
|
||||
<annotationProcessor>org.checkerframework.checker.regex.RegexChecker</annotationProcessor>
|
||||
</annotationProcessors>
|
||||
<compilerArgs>
|
||||
<arg>-AprintErrorStack</arg>
|
||||
|
||||
<!-- location of the annotated JDK, which comes from a Maven dependency -->
|
||||
<arg>-Xbootclasspath/p:${annotatedJdk}</arg>
|
||||
<!--
|
||||
-->
|
||||
|
||||
<!-- Uncomment the following line to use the type annotations compiler. -->
|
||||
<!--
|
||||
<arg>-J-Xbootclasspath/p:${typeAnnotationsJavac}</arg>
|
||||
-->
|
||||
<!-- Uncomment the following line to turn type-checking warnings into errors. -->
|
||||
<arg>-Awarns</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.typechecker;
|
||||
|
||||
import org.checkerframework.checker.fenum.qual.Fenum;
|
||||
|
||||
//@SuppressWarnings("fenum:assignment.type.incompatible")
|
||||
public class FakeNumExample {
|
||||
|
||||
// Here we use some String constants to represents countries.
|
||||
static final @Fenum("country") String ITALY = "IT";
|
||||
static final @Fenum("country") String US = "US";
|
||||
static final @Fenum("country") String UNITED_KINGDOM = "UK";
|
||||
|
||||
// Here we use other String constants to represent planets instead.
|
||||
static final @Fenum("planet") String MARS = "Mars";
|
||||
static final @Fenum("planet") String EARTH = "Earth";
|
||||
static final @Fenum("planet") String VENUS = "Venus";
|
||||
|
||||
// Now we write this method and we want to be sure that
|
||||
// the String parameter has a value of a country, not that is just a String.
|
||||
void greetCountries(@Fenum("country") String country) {
|
||||
System.out.println("Hello " + country);
|
||||
}
|
||||
|
||||
// Similarly we're enforcing here that the provided
|
||||
// parameter is a String that represent a planet.
|
||||
void greetPlanets(@Fenum("planet") String planet) {
|
||||
System.out.println("Hello " + planet);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
FakeNumExample obj = new FakeNumExample();
|
||||
|
||||
// This will fail because we pass a planet-String to a method that
|
||||
// accept a country-String.
|
||||
obj.greetCountries(MARS);
|
||||
|
||||
// Here the opposite happens.
|
||||
obj.greetPlanets(US);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.typechecker;
|
||||
|
||||
public class FormatExample {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
// Just enabling org.checkerframework.checker.formatter.FormatterChecker
|
||||
// we can be sure at compile time that the format strings we pass to format()
|
||||
// are correct. Normally we would have those errors raised just at runtime.
|
||||
// All those formats are in fact wrong.
|
||||
|
||||
String.format("%y", 7); // error: invalid format string
|
||||
|
||||
String.format("%d", "a string"); // error: invalid argument type for %d
|
||||
|
||||
String.format("%d %s", 7); // error: missing argument for %s
|
||||
|
||||
String.format("%d", 7, 3); // warning: unused argument 3
|
||||
|
||||
String.format("{0}", 7); // warning: unused argument 7, because {0} is wrong syntax
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.typechecker;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.KeyFor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class KeyForExample {
|
||||
|
||||
private final Map<String, String> config = new HashMap<>();
|
||||
|
||||
KeyForExample() {
|
||||
|
||||
// Here we initialize a map to store
|
||||
// some config data.
|
||||
config.put("url", "http://1.2.3.4");
|
||||
config.put("name", "foobaz");
|
||||
}
|
||||
|
||||
public void dumpPort() {
|
||||
|
||||
// Here, we want to dump the port value stored in the
|
||||
// config, so we declare that this key has to be
|
||||
// present in the config map.
|
||||
// Obviously that will fail because such key is not present
|
||||
// in the map.
|
||||
@KeyFor("config") String key = "port";
|
||||
System.out.println( config.get(key) );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.typechecker;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class MonotonicNotNullExample {
|
||||
|
||||
// The idea is we need this field to be to lazily initialized,
|
||||
// so it starts as null but once it becomes not null
|
||||
// it cannot return null.
|
||||
// In these cases, we can use @MonotonicNonNull
|
||||
@MonotonicNonNull private Date firstCall;
|
||||
|
||||
public Date getFirstCall() {
|
||||
if (firstCall == null) {
|
||||
firstCall = new Date();
|
||||
}
|
||||
return firstCall;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
// This is reported as error because
|
||||
// we wrongly set the field back to null.
|
||||
firstCall = null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.baeldung.typechecker;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class NonNullExample {
|
||||
|
||||
// This method's parameter is annotated in order
|
||||
// to tell the pluggable type system that it can never be null.
|
||||
private static int countArgs(@NonNull String[] args) {
|
||||
return args.length;
|
||||
}
|
||||
|
||||
// This method's parameter is annotated in order
|
||||
// to tell the pluggable type system that it may be null.
|
||||
public static void main(@Nullable String[] args) {
|
||||
|
||||
// Here lies a potential error,
|
||||
// because we pass a potential null reference to a method
|
||||
// that does not accept nulls.
|
||||
// The Checker Framework will spot this problem at compile time
|
||||
// instead of runtime.
|
||||
System.out.println(countArgs(args));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.typechecker;
|
||||
|
||||
import org.checkerframework.checker.regex.qual.Regex;
|
||||
|
||||
public class RegexExample {
|
||||
|
||||
// For some reason we want to be sure that this regex
|
||||
// contains at least one capturing group.
|
||||
// However, we do an error and we forgot to define such
|
||||
// capturing group in it.
|
||||
@Regex(1) private static String findNumbers = "\\d*";
|
||||
|
||||
public static void main(String[] args) {
|
||||
String message = "My phone number is +3911223344.";
|
||||
message.matches(findNumbers);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# Groovy
|
||||
|
||||
## Relevant articles:
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
<?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>core-groovy</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>central</id>
|
||||
<url>http://jcenter.bintray.com</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
<version>2.4.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-sql</artifactId>
|
||||
<version>2.4.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-runner</artifactId>
|
||||
<version>${junit.platform.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.4.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmavenplus</groupId>
|
||||
<artifactId>gmavenplus-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>addSources</goal>
|
||||
<goal>addTestSources</goal>
|
||||
<goal>compile</goal>
|
||||
<goal>compileTests</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.19.1</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-surefire-provider</artifactId>
|
||||
<version>${junit.platform.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>junit5</id>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Test5.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<kotlin-maven-plugin.version>1.1.2</kotlin-maven-plugin.version>
|
||||
<kotlin-test-junit.version>1.1.2</kotlin-test-junit.version>
|
||||
<kotlin-stdlib.version>1.1.2</kotlin-stdlib.version>
|
||||
<kotlin-reflect.version>1.1.2</kotlin-reflect.version>
|
||||
<kotlinx.version>0.15</kotlinx.version>
|
||||
<mockito-kotlin.version>1.5.0</mockito-kotlin.version>
|
||||
|
||||
<junit.jupiter.version>5.0.0</junit.jupiter.version>
|
||||
<junit.platform.version>1.0.0</junit.platform.version>
|
||||
<junit.vintage.version>4.12.0</junit.vintage.version>
|
||||
<junit4.version>4.12</junit4.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,229 @@
|
||||
package com.baeldung.groovy.sql
|
||||
|
||||
import groovy.sql.GroovyResultSet
|
||||
import groovy.sql.GroovyRowResult
|
||||
import groovy.sql.Sql
|
||||
import groovy.transform.CompileStatic
|
||||
import static org.junit.Assert.*
|
||||
import org.junit.Test
|
||||
|
||||
class SqlTest {
|
||||
|
||||
final Map dbConnParams = [url: 'jdbc:hsqldb:mem:testDB', user: 'sa', password: '', driver: 'org.hsqldb.jdbc.JDBCDriver']
|
||||
|
||||
@Test
|
||||
void whenNewSqlInstance_thenDbIsAccessed() {
|
||||
def sql = Sql.newInstance(dbConnParams)
|
||||
sql.close()
|
||||
sql.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenTableDoesNotExist_thenSelectFails() {
|
||||
try {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
sql.eachRow('select * from PROJECT') {}
|
||||
}
|
||||
|
||||
fail("An exception should have been thrown")
|
||||
} catch (ignored) {
|
||||
//Ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenTableCreated_thenSelectIsPossible() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
def result = sql.execute 'create table PROJECT_1 (id integer not null, name varchar(50), url varchar(100))'
|
||||
|
||||
assertEquals(0, sql.updateCount)
|
||||
assertFalse(result)
|
||||
|
||||
result = sql.execute('select * from PROJECT_1')
|
||||
|
||||
assertTrue(result)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenIdentityColumn_thenInsertReturnsNewId() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
sql.execute 'create table PROJECT_2 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
def ids = sql.executeInsert("INSERT INTO PROJECT_2 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
|
||||
|
||||
assertEquals(0, ids[0][0])
|
||||
|
||||
ids = sql.executeInsert("INSERT INTO PROJECT_2 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
|
||||
|
||||
assertEquals(1, ids[0][0])
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUpdate_thenNumberOfAffectedRows() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
sql.execute 'create table PROJECT_3 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
sql.executeInsert("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
|
||||
sql.executeInsert("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
|
||||
def count = sql.executeUpdate("UPDATE PROJECT_3 SET URL = 'https://' + URL")
|
||||
|
||||
assertEquals(2, count)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenEachRow_thenResultSetHasProperties() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
sql.execute 'create table PROJECT_4 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
sql.executeInsert("INSERT INTO PROJECT_4 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
|
||||
sql.executeInsert("INSERT INTO PROJECT_4 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
|
||||
|
||||
sql.eachRow("SELECT * FROM PROJECT_4") { GroovyResultSet rs ->
|
||||
assertNotNull(rs.name)
|
||||
assertNotNull(rs.url)
|
||||
assertNotNull(rs[0])
|
||||
assertNotNull(rs[1])
|
||||
assertNotNull(rs[2])
|
||||
assertEquals(rs.name, rs['name'])
|
||||
assertEquals(rs.url, rs['url'])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPagination_thenSubsetIsReturned() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
sql.execute 'create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
|
||||
sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
|
||||
def rows = sql.rows('SELECT * FROM PROJECT_5 ORDER BY NAME', 1, 1)
|
||||
|
||||
assertEquals(1, rows.size())
|
||||
assertEquals('REST with Spring', rows[0].name)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenParameters_thenReplacement() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
sql.execute 'create table PROJECT_6 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
sql.execute('INSERT INTO PROJECT_6 (NAME, URL) VALUES (?, ?)', 'tutorials', 'github.com/eugenp/tutorials')
|
||||
sql.execute("INSERT INTO PROJECT_6 (NAME, URL) VALUES (:name, :url)", [name: 'REST with Spring', url: 'github.com/eugenp/REST-With-Spring'])
|
||||
|
||||
def rows = sql.rows("SELECT * FROM PROJECT_6 WHERE NAME = 'tutorials'")
|
||||
|
||||
assertEquals(1, rows.size())
|
||||
|
||||
rows = sql.rows("SELECT * FROM PROJECT_6 WHERE NAME = 'REST with Spring'")
|
||||
|
||||
assertEquals(1, rows.size())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenParametersInGString_thenReplacement() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
sql.execute 'create table PROJECT_7 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
sql.execute "INSERT INTO PROJECT_7 (NAME, URL) VALUES (${'tutorials'}, ${'github.com/eugenp/tutorials'})"
|
||||
def name = 'REST with Spring'
|
||||
def url = 'github.com/eugenp/REST-With-Spring'
|
||||
sql.execute "INSERT INTO PROJECT_7 (NAME, URL) VALUES (${name}, ${url})"
|
||||
|
||||
def rows = sql.rows("SELECT * FROM PROJECT_7 WHERE NAME = 'tutorials'")
|
||||
|
||||
assertEquals(1, rows.size())
|
||||
|
||||
rows = sql.rows("SELECT * FROM PROJECT_7 WHERE NAME = 'REST with Spring'")
|
||||
|
||||
assertEquals(1, rows.size())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenTransactionRollback_thenNoDataInserted() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
sql.withTransaction {
|
||||
sql.execute 'create table PROJECT_8 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
sql.executeInsert("INSERT INTO PROJECT_8 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
|
||||
sql.executeInsert("INSERT INTO PROJECT_8 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
|
||||
sql.rollback()
|
||||
|
||||
def rows = sql.rows("SELECT * FROM PROJECT_8")
|
||||
|
||||
assertEquals(0, rows.size())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenTransactionRollbackThenCommit_thenOnlyLastInserted() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
sql.withTransaction {
|
||||
sql.execute 'create table PROJECT_9 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
sql.executeInsert("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
|
||||
sql.rollback()
|
||||
sql.executeInsert("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
|
||||
sql.rollback()
|
||||
sql.executeInsert("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
|
||||
sql.executeInsert("INSERT INTO PROJECT_9 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')")
|
||||
}
|
||||
|
||||
def rows = sql.rows("SELECT * FROM PROJECT_9")
|
||||
|
||||
assertEquals(2, rows.size())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenException_thenTransactionIsRolledBack() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
try {
|
||||
sql.withTransaction {
|
||||
sql.execute 'create table PROJECT_10 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
sql.executeInsert("INSERT INTO PROJECT_10 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
|
||||
throw new Exception('rollback')
|
||||
}
|
||||
} catch (ignored) {}
|
||||
|
||||
def rows = sql.rows("SELECT * FROM PROJECT_10")
|
||||
|
||||
assertEquals(0, rows.size())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenCachedConnection_whenException_thenDataIsPersisted() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
try {
|
||||
sql.cacheConnection {
|
||||
sql.execute 'create table PROJECT_11 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
sql.executeInsert("INSERT INTO PROJECT_11 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')")
|
||||
throw new Exception('This does not rollback')
|
||||
}
|
||||
} catch (ignored) {}
|
||||
|
||||
def rows = sql.rows("SELECT * FROM PROJECT_11")
|
||||
|
||||
assertEquals(1, rows.size())
|
||||
}
|
||||
}
|
||||
|
||||
/*@Test
|
||||
void whenModifyResultSet_thenDataIsChanged() {
|
||||
Sql.withInstance(dbConnParams) { Sql sql ->
|
||||
sql.execute 'create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))'
|
||||
sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')")
|
||||
sql.executeInsert("INSERT INTO PROJECT_5 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')")
|
||||
|
||||
sql.eachRow("SELECT * FROM PROJECT_5 FOR UPDATE ") { GroovyResultSet rs ->
|
||||
rs['name'] = "The great ${rs.name}!" as String
|
||||
rs.updateRow()
|
||||
}
|
||||
|
||||
sql.eachRow("SELECT * FROM PROJECT_5") { GroovyResultSet rs ->
|
||||
assertTrue(rs.name.startsWith('The great '))
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
@@ -40,3 +40,4 @@
|
||||
- [Efficient Word Frequency Calculator in Java](http://www.baeldung.com/java-word-frequency)
|
||||
- [Primitive Type Streams in Java 8](http://www.baeldung.com/java-8-primitive-streams)
|
||||
- [Fail-Safe Iterator vs Fail-Fast Iterator](http://www.baeldung.com/java-fail-safe-vs-fail-fast-iterator)
|
||||
- [Shuffling Collections In Java](http://www.baeldung.com/java-shuffle-collection)
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package com.baeldung.shufflingcollections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ShufflingCollectionsUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenShufflingList_thenListIsShuffled() {
|
||||
List<String> students = Arrays.asList("Foo", "Bar", "Baz", "Qux");
|
||||
|
||||
System.out.println("List before shuffling:");
|
||||
System.out.println(students);
|
||||
|
||||
Collections.shuffle(students);
|
||||
System.out.println("List after shuffling:");
|
||||
System.out.println(students);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenShufflingMapEntries_thenValuesAreShuffled() {
|
||||
Map<Integer, String> studentsById = new HashMap<>();
|
||||
studentsById.put(1, "Foo");
|
||||
studentsById.put(2, "Bar");
|
||||
studentsById.put(3, "Baz");
|
||||
studentsById.put(4, "Qux");
|
||||
|
||||
System.out.println("Students before shuffling:");
|
||||
System.out.println(studentsById.values());
|
||||
|
||||
List<Map.Entry<Integer, String>> shuffledStudentEntries = new ArrayList<>(studentsById.entrySet());
|
||||
Collections.shuffle(shuffledStudentEntries);
|
||||
|
||||
List<String> shuffledStudents = shuffledStudentEntries.stream()
|
||||
.map(Map.Entry::getValue)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
System.out.println("Students after shuffling");
|
||||
System.out.println(shuffledStudents);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenShufflingSet_thenElementsAreShuffled() {
|
||||
Set<String> students = new HashSet<>(Arrays.asList("Foo", "Bar", "Baz", "Qux"));
|
||||
|
||||
System.out.println("Set before shuffling:");
|
||||
System.out.println(students);
|
||||
|
||||
List<String> studentList = new ArrayList<>(students);
|
||||
|
||||
Collections.shuffle(studentList);
|
||||
System.out.println("Shuffled set elements:");
|
||||
System.out.println(studentList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenShufflingWithSameRandomness_thenElementsAreShuffledDeterministically() {
|
||||
List<String> students_1 = Arrays.asList("Foo", "Bar", "Baz", "Qux");
|
||||
List<String> students_2 = Arrays.asList("Foo", "Bar", "Baz", "Qux");
|
||||
|
||||
Collections.shuffle(students_1, new Random(5));
|
||||
Collections.shuffle(students_2, new Random(5));
|
||||
|
||||
assertThat(students_1).isEqualTo(students_2);
|
||||
}
|
||||
}
|
||||
-126
@@ -1,126 +0,0 @@
|
||||
package com.baeldung.java9.httpclient;
|
||||
|
||||
import static java.net.HttpURLConnection.HTTP_OK;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookiePolicy;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpHeaders;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SimpleHttpRequestsUnitTest {
|
||||
|
||||
private URI httpURI;
|
||||
|
||||
@Before
|
||||
public void init() throws URISyntaxException {
|
||||
httpURI = new URI("http://www.baeldung.com/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quickGet() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.create(httpURI).GET();
|
||||
HttpResponse response = request.response();
|
||||
int responseStatusCode = response.statusCode();
|
||||
String responseBody = response.body(HttpResponse.asString());
|
||||
assertTrue("Get response status code is bigger then 400", responseStatusCode < 400);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asynchronousGet() throws URISyntaxException, IOException, InterruptedException, ExecutionException {
|
||||
HttpRequest request = HttpRequest.create(httpURI).GET();
|
||||
long before = System.currentTimeMillis();
|
||||
CompletableFuture<HttpResponse> futureResponse = request.responseAsync();
|
||||
futureResponse.thenAccept(response -> {
|
||||
String responseBody = response.body(HttpResponse.asString());
|
||||
});
|
||||
HttpResponse resp = futureResponse.get();
|
||||
HttpHeaders hs = resp.headers();
|
||||
assertTrue("There should be more then 1 header.", hs.map().size() > 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postMehtod() throws URISyntaxException, IOException, InterruptedException {
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.create(httpURI);
|
||||
requestBuilder.body(HttpRequest.fromString("param1=foo,param2=bar")).followRedirects(HttpClient.Redirect.SECURE);
|
||||
HttpRequest request = requestBuilder.POST();
|
||||
HttpResponse response = request.response();
|
||||
int statusCode = response.statusCode();
|
||||
assertTrue("HTTP return code", statusCode == HTTP_OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureHttpClient() throws NoSuchAlgorithmException, URISyntaxException, IOException, InterruptedException {
|
||||
CookieManager cManager = new CookieManager();
|
||||
cManager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
|
||||
|
||||
SSLParameters sslParam = new SSLParameters(new String[] { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" }, new String[] { "TLSv1.2" });
|
||||
|
||||
HttpClient.Builder hcBuilder = HttpClient.create();
|
||||
hcBuilder.cookieManager(cManager).sslContext(SSLContext.getDefault()).sslParameters(sslParam);
|
||||
HttpClient httpClient = hcBuilder.build();
|
||||
HttpRequest.Builder reqBuilder = httpClient.request(new URI("https://www.facebook.com"));
|
||||
|
||||
HttpRequest request = reqBuilder.followRedirects(HttpClient.Redirect.ALWAYS).GET();
|
||||
HttpResponse response = request.response();
|
||||
int statusCode = response.statusCode();
|
||||
assertTrue("HTTP return code", statusCode == HTTP_OK);
|
||||
}
|
||||
|
||||
SSLParameters getDefaultSSLParameters() throws NoSuchAlgorithmException {
|
||||
SSLParameters sslP1 = SSLContext.getDefault().getSupportedSSLParameters();
|
||||
String[] proto = sslP1.getApplicationProtocols();
|
||||
String[] cifers = sslP1.getCipherSuites();
|
||||
System.out.println(printStringArr(proto));
|
||||
System.out.println(printStringArr(cifers));
|
||||
return sslP1;
|
||||
}
|
||||
|
||||
String printStringArr(String... args) {
|
||||
if (args == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String s : args) {
|
||||
sb.append(s);
|
||||
sb.append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
String printHeaders(HttpHeaders h) {
|
||||
if (h == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Map<String, List<String>> hMap = h.map();
|
||||
for (String k : hMap.keySet()) {
|
||||
sb.append(k).append(":");
|
||||
List<String> l = hMap.get(k);
|
||||
if (l != null) {
|
||||
l.forEach(s -> {
|
||||
sb.append(s).append(",");
|
||||
});
|
||||
}
|
||||
sb.append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -16,7 +16,8 @@ public class Job implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
System.out.println("Job:" + jobName + " Priority:" + jobPriority);
|
||||
System.out.println("Job:" + jobName +
|
||||
" Priority:" + jobPriority);
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
|
||||
+6
-6
@@ -9,21 +9,21 @@ import java.util.concurrent.TimeUnit;
|
||||
public class PriorityJobScheduler {
|
||||
|
||||
private ExecutorService priorityJobPoolExecutor;
|
||||
private ExecutorService priorityJobScheduler;
|
||||
private PriorityBlockingQueue<Runnable> priorityQueue;
|
||||
private ExecutorService priorityJobScheduler =
|
||||
Executors.newSingleThreadExecutor();
|
||||
private PriorityBlockingQueue<Job> priorityQueue;
|
||||
|
||||
public PriorityJobScheduler(Integer poolSize, Integer queueSize) {
|
||||
priorityJobPoolExecutor = Executors.newFixedThreadPool(poolSize);
|
||||
Comparator<? super Job> jobComparator = Comparator.comparing(Job::getJobPriority);
|
||||
priorityQueue = new PriorityBlockingQueue<Runnable>(queueSize,
|
||||
(Comparator<? super Runnable>) jobComparator);
|
||||
priorityQueue = new PriorityBlockingQueue<Job>(queueSize,
|
||||
Comparator.comparing(Job::getJobPriority));
|
||||
|
||||
priorityJobScheduler = Executors.newSingleThreadExecutor();
|
||||
priorityJobScheduler.execute(()->{
|
||||
while (true) {
|
||||
try {
|
||||
priorityJobPoolExecutor.execute(priorityQueue.take());
|
||||
} catch (InterruptedException e) {
|
||||
// exception needs special handling
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.concurrent.threadlifecycle;
|
||||
|
||||
public class BlockedState {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
Thread t1 = new Thread(new DemoThreadB());
|
||||
Thread t2 = new Thread(new DemoThreadB());
|
||||
|
||||
t1.start();
|
||||
t2.start();
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
System.out.println(t2.getState());
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
class DemoThreadB implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
commonResource();
|
||||
}
|
||||
|
||||
public static synchronized void commonResource() {
|
||||
while(true) {
|
||||
// Infinite loop to mimic heavy processing
|
||||
// Thread 't1' won't leave this method
|
||||
// when Thread 't2' enters this
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.concurrent.threadlifecycle;
|
||||
|
||||
public class NewState implements Runnable {
|
||||
public static void main(String[] args) {
|
||||
Runnable runnable = new NewState();
|
||||
Thread t = new Thread(runnable);
|
||||
System.out.println(t.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.concurrent.threadlifecycle;
|
||||
|
||||
public class RunnableState implements Runnable {
|
||||
public static void main(String[] args) {
|
||||
Runnable runnable = new NewState();
|
||||
Thread t = new Thread(runnable);
|
||||
t.start();
|
||||
System.out.println(t.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user