readFileInList(String filePath) {
+ File file = new File(filePath)
+ def lines = file.readLines()
+ return lines
+ }
+
+ /**
+ * reads file content in string using File.text
+ * @param filePath
+ * @return
+ */
+ String readFileString(String filePath) {
+ File file = new File(filePath)
+ String fileContent = file.text
+ return fileContent
+ }
+
+ /**
+ * reads file content in string with encoding using File.getText
+ * @param filePath
+ * @return
+ */
+ String readFileStringWithCharset(String filePath) {
+ File file = new File(filePath)
+ String utf8Content = file.getText("UTF-8")
+ return utf8Content
+ }
+
+ /**
+ * reads content of binary file and returns byte array
+ * @param filePath
+ * @return
+ */
+ byte[] readBinaryFile(String filePath) {
+ File file = new File(filePath)
+ byte[] binaryContent = file.bytes
+ return binaryContent
+ }
+
+ /**
+ * More Examples of reading a file
+ * @return
+ */
+ def moreExamples() {
+
+ //with reader with utf-8
+ new File("src/main/resources/utf8Content.html").withReader('UTF-8') { reader ->
+ def line
+ while ((line = reader.readLine())!=null) {
+ println "${line}"
+ }
+ }
+
+ //collect api
+ def list = new File("src/main/resources/fileContent.txt").collect {it}
+
+ //as operator
+ def array = new File("src/main/resources/fileContent.txt") as String[]
+
+ //eachline
+ new File("src/main/resources/fileContent.txt").eachLine { line ->
+ println line
+ }
+
+ //newInputStream with eachLine
+ def is = new File("src/main/resources/fileContent.txt").newInputStream()
+ is.eachLine {
+ println it
+ }
+ is.close()
+
+ //withInputStream
+ new File("src/main/resources/fileContent.txt").withInputStream { stream ->
+ stream.eachLine { line ->
+ println line
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/io/Task.groovy b/core-groovy/src/main/groovy/com/baeldung/io/Task.groovy
new file mode 100644
index 0000000000..8a3bedc048
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/io/Task.groovy
@@ -0,0 +1,8 @@
+package com.baeldung.io
+
+class Task implements Serializable {
+ String description
+ Date startDate
+ Date dueDate
+ int status
+}
diff --git a/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy b/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy
new file mode 100644
index 0000000000..b3a0852a0b
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy
@@ -0,0 +1,43 @@
+package com.baeldung.strings;
+
+class Concatenate {
+ String first = 'Hello'
+ String last = 'Groovy'
+
+ String doSimpleConcat() {
+ return 'My name is ' + first + ' ' + last
+ }
+
+ String doConcatUsingGString() {
+ return "My name is $first $last"
+ }
+
+ String doConcatUsingGStringClosures() {
+ return "My name is ${-> first} ${-> last}"
+ }
+
+ String doConcatUsingStringConcatMethod() {
+ return 'My name is '.concat(first).concat(' ').concat(last)
+ }
+
+ String doConcatUsingLeftShiftOperator() {
+ return 'My name is ' << first << ' ' << last
+ }
+
+ String doConcatUsingArrayJoinMethod() {
+ return ['My name is', first, last].join(' ')
+ }
+
+ String doConcatUsingArrayInjectMethod() {
+ return [first,' ', last]
+ .inject(new StringBuffer('My name is '), { initial, name -> initial.append(name); return initial }).toString()
+ }
+
+ String doConcatUsingStringBuilder() {
+ return new StringBuilder().append('My name is ').append(first).append(' ').append(last)
+ }
+
+ String doConcatUsingStringBuffer() {
+ return new StringBuffer().append('My name is ').append(first).append(' ').append(last)
+ }
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy
new file mode 100644
index 0000000000..6ec5cda571
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy
@@ -0,0 +1,8 @@
+package com.baeldung.traits
+
+trait AnimalTrait {
+
+ String basicBehavior() {
+ return "Animalistic!!"
+ }
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy
new file mode 100644
index 0000000000..eb4d1f7f87
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy
@@ -0,0 +1,3 @@
+package com.baeldung
+
+class Car implements VehicleTrait {}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy
new file mode 100644
index 0000000000..3e0677ba18
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy
@@ -0,0 +1,9 @@
+package com.baeldung.traits
+
+class Dog implements WalkingTrait, SpeakingTrait {
+
+ String speakAndWalk() {
+ WalkingTrait.super.speakAndWalk()
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy
new file mode 100644
index 0000000000..b3e4285476
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy
@@ -0,0 +1,12 @@
+package com.baeldung.traits
+
+class Employee implements UserTrait {
+
+ String name() {
+ return 'Bob'
+ }
+
+ String lastName() {
+ return "Marley"
+ }
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy
new file mode 100644
index 0000000000..e78d59bbfd
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy
@@ -0,0 +1,6 @@
+package com.baeldung.traits
+
+interface Human {
+
+ String lastName()
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy
new file mode 100644
index 0000000000..f437a94bd9
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy
@@ -0,0 +1,13 @@
+package com.baeldung.traits
+
+trait SpeakingTrait {
+
+ String basicAbility() {
+ return "Speaking!!"
+ }
+
+ String speakAndWalk() {
+ return "Speak and walk!!"
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy
new file mode 100644
index 0000000000..0d395bffcd
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy
@@ -0,0 +1,36 @@
+package com.baeldung.traits
+
+trait UserTrait implements Human {
+
+ String sayHello() {
+ return "Hello!"
+ }
+
+ abstract String name()
+
+ String showName() {
+ return "Hello, ${name()}!"
+ }
+
+ private String greetingMessage() {
+ return 'Hello, from a private method!'
+ }
+
+ String greet() {
+ def msg = greetingMessage()
+ println msg
+ msg
+ }
+
+ def self() {
+ return this
+ }
+
+ String showLastName() {
+ return "Hello, ${lastName()}!"
+ }
+
+ String email
+ String address
+}
+
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy
new file mode 100644
index 0000000000..f5ae8fab30
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy
@@ -0,0 +1,9 @@
+package com.baeldung
+
+trait VehicleTrait extends WheelTrait {
+
+ String showWheels() {
+ return "Num of Wheels $noOfWheels"
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy
new file mode 100644
index 0000000000..66cff8809f
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy
@@ -0,0 +1,13 @@
+package com.baeldung.traits
+
+trait WalkingTrait {
+
+ String basicAbility() {
+ return "Walking!!"
+ }
+
+ String speakAndWalk() {
+ return "Walk and speak!!"
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy
new file mode 100644
index 0000000000..364d5b883e
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy
@@ -0,0 +1,7 @@
+package com.baeldung
+
+trait WheelTrait {
+
+ int noOfWheels
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/resources/binaryExample.jpg b/core-groovy/src/main/resources/binaryExample.jpg
new file mode 100644
index 0000000000..4b32645ac9
Binary files /dev/null and b/core-groovy/src/main/resources/binaryExample.jpg differ
diff --git a/core-groovy/src/main/resources/fileContent.txt b/core-groovy/src/main/resources/fileContent.txt
new file mode 100644
index 0000000000..643e4af3de
--- /dev/null
+++ b/core-groovy/src/main/resources/fileContent.txt
@@ -0,0 +1,3 @@
+Line 1 : Hello World!!!
+Line 2 : This is a file content.
+Line 3 : String content
diff --git a/core-groovy/src/main/resources/ioData.txt b/core-groovy/src/main/resources/ioData.txt
new file mode 100644
index 0000000000..d2741339d1
Binary files /dev/null and b/core-groovy/src/main/resources/ioData.txt differ
diff --git a/core-groovy/src/main/resources/ioInput.txt b/core-groovy/src/main/resources/ioInput.txt
new file mode 100644
index 0000000000..b180256dd5
--- /dev/null
+++ b/core-groovy/src/main/resources/ioInput.txt
@@ -0,0 +1,4 @@
+First line of text
+Second line of text
+Third line of text
+Fourth line of text
\ No newline at end of file
diff --git a/core-groovy/src/main/resources/ioOutput.txt b/core-groovy/src/main/resources/ioOutput.txt
new file mode 100644
index 0000000000..bcf76c43d8
--- /dev/null
+++ b/core-groovy/src/main/resources/ioOutput.txt
@@ -0,0 +1,3 @@
+Line one of output example
+Line two of output example
+Line three of output example
\ No newline at end of file
diff --git a/core-groovy/src/main/resources/ioSerializedObject.txt b/core-groovy/src/main/resources/ioSerializedObject.txt
new file mode 100644
index 0000000000..833ed32bf1
Binary files /dev/null and b/core-groovy/src/main/resources/ioSerializedObject.txt differ
diff --git a/core-groovy/src/main/resources/sample.png b/core-groovy/src/main/resources/sample.png
new file mode 100644
index 0000000000..7d473430b7
Binary files /dev/null and b/core-groovy/src/main/resources/sample.png differ
diff --git a/core-groovy/src/main/resources/utf8Content.html b/core-groovy/src/main/resources/utf8Content.html
new file mode 100644
index 0000000000..61ff338f6c
--- /dev/null
+++ b/core-groovy/src/main/resources/utf8Content.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ
+ᛋᚳᛖᚪᛚ᛫ᚦᛖᚪᚻ᛫ᛗᚪᚾᚾᚪ᛫ᚷᛖᚻᚹᛦᛚᚳ᛫ᛗᛁᚳᛚᚢᚾ᛫ᚻᛦᛏ᛫ᛞᚫᛚᚪᚾ
+ᚷᛁᚠ᛫ᚻᛖ᛫ᚹᛁᛚᛖ᛫ᚠᚩᚱ᛫ᛞᚱᛁᚻᛏᚾᛖ᛫ᛞᚩᛗᛖᛋ᛫ᚻᛚᛇᛏᚪᚾ
+
+
+
\ No newline at end of file
diff --git a/core-groovy/src/test/groovy/com/baeldung/date/DateTest.groovy b/core-groovy/src/test/groovy/com/baeldung/date/DateTest.groovy
new file mode 100644
index 0000000000..4e7a7189a6
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/date/DateTest.groovy
@@ -0,0 +1,57 @@
+package com.baeldung.groovy.sql
+
+import static org.junit.Assert.*
+import java.util.Calendar.*
+import java.time.LocalDate
+import java.text.SimpleDateFormat
+import org.junit.Test
+
+
+class DateTest {
+
+ def dateStr = "2019-02-28"
+ def pattern = "yyyy-MM-dd"
+
+ @Test
+ void whenGetStringRepresentation_thenCorrectlyConvertIntoDate() {
+ def dateFormat = new SimpleDateFormat(pattern)
+ def date = dateFormat.parse(dateStr)
+
+ println(" String to Date with DateFormatter : " + date)
+
+ def cal = new GregorianCalendar();
+ cal.setTime(date);
+
+ assertEquals(cal.get(Calendar.YEAR),2019)
+ assertEquals(cal.get(Calendar.DAY_OF_MONTH),28)
+ assertEquals(cal.get(Calendar.MONTH),java.util.Calendar.FEBRUARY)
+ }
+
+ @Test
+ void whenGetStringRepresentation_thenCorrectlyConvertWithDateUtilsExtension() {
+
+ def date = Date.parse(pattern, dateStr)
+
+ println(" String to Date with Date.parse : " + date)
+
+ def cal = new GregorianCalendar();
+ cal.setTime(date);
+
+ assertEquals(cal.get(Calendar.YEAR),2019)
+ assertEquals(cal.get(Calendar.DAY_OF_MONTH),28)
+ assertEquals(cal.get(Calendar.MONTH),java.util.Calendar.FEBRUARY)
+ }
+
+ @Test
+ void whenGetStringRepresentation_thenCorrectlyConvertIntoDateWithLocalDate() {
+ def date = LocalDate.parse(dateStr, pattern)
+
+ println(" String to Date with LocalDate : " + date)
+
+ assertEquals(date.getYear(),2019)
+ assertEquals(date.getMonth(),java.time.Month.FEBRUARY)
+ assertEquals(date.getDayOfMonth(),28)
+ }
+
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy
new file mode 100644
index 0000000000..a479c265c4
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy
@@ -0,0 +1,70 @@
+package com.baeldung.file
+
+import spock.lang.Specification
+
+class ReadFileUnitTest extends Specification {
+
+ ReadFile readFile
+
+ void setup () {
+ readFile = new ReadFile()
+ }
+
+ def 'Should return number of lines in File using ReadFile.readFileLineByLine given filePath' () {
+ given:
+ def filePath = "src/main/resources/fileContent.txt"
+ when:
+ def noOfLines = readFile.readFileLineByLine(filePath)
+ then:
+ noOfLines
+ noOfLines instanceof Integer
+ assert noOfLines, 3
+ }
+
+ def 'Should return File Content in list of lines using ReadFile.readFileInList given filePath' () {
+ given:
+ def filePath = "src/main/resources/fileContent.txt"
+ when:
+ def lines = readFile.readFileInList(filePath)
+ then:
+ lines
+ lines instanceof List
+ assert lines.size(), 3
+ }
+
+ def 'Should return file content in string using ReadFile.readFileString given filePath' () {
+ given:
+ def filePath = "src/main/resources/fileContent.txt"
+ when:
+ def fileContent = readFile.readFileString(filePath)
+ then:
+ fileContent
+ fileContent instanceof String
+ fileContent.contains("""Line 1 : Hello World!!!
+Line 2 : This is a file content.
+Line 3 : String content""")
+
+ }
+
+ def 'Should return UTF-8 encoded file content in string using ReadFile.readFileStringWithCharset given filePath' () {
+ given:
+ def filePath = "src/main/resources/utf8Content.html"
+ when:
+ def encodedContent = readFile.readFileStringWithCharset(filePath)
+ then:
+ encodedContent
+ encodedContent instanceof String
+ }
+
+ def 'Should return binary file content in byte array using ReadFile.readBinaryFile given filePath' () {
+ given:
+ def filePath = "src/main/resources/sample.png"
+ when:
+ def binaryContent = readFile.readBinaryFile(filePath)
+ then:
+ binaryContent
+ binaryContent instanceof byte[]
+ binaryContent.length == 329
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/test/groovy/com/baeldung/io/DataAndObjectsUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/DataAndObjectsUnitTest.groovy
new file mode 100644
index 0000000000..0b413cf76c
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/io/DataAndObjectsUnitTest.groovy
@@ -0,0 +1,51 @@
+package com.baeldung.io
+
+import static org.junit.Assert.*
+
+import org.junit.Test
+
+class DataAndObjectsUnitTest {
+ @Test
+ void whenUsingWithDataOutputStream_thenDataIsSerializedToAFile() {
+ String message = 'This is a serialized string'
+ int length = message.length()
+ boolean valid = true
+ new File('src/main/resources/ioData.txt').withDataOutputStream { out ->
+ out.writeUTF(message)
+ out.writeInt(length)
+ out.writeBoolean(valid)
+ }
+
+ String loadedMessage = ""
+ int loadedLength
+ boolean loadedValid
+
+ new File('src/main/resources/ioData.txt').withDataInputStream { is ->
+ loadedMessage = is.readUTF()
+ loadedLength = is.readInt()
+ loadedValid = is.readBoolean()
+ }
+
+ assertEquals(message, loadedMessage)
+ assertEquals(length, loadedLength)
+ assertEquals(valid, loadedValid)
+ }
+
+ @Test
+ void whenUsingWithObjectOutputStream_thenObjectIsSerializedToFile() {
+ Task task = new Task(description:'Take out the trash', startDate:new Date(), status:0)
+ new File('src/main/resources/ioSerializedObject.txt').withObjectOutputStream { out ->
+ out.writeObject(task)
+ }
+
+ Task taskRead
+
+ new File('src/main/resources/ioSerializedObject.txt').withObjectInputStream { is ->
+ taskRead = is.readObject()
+ }
+
+ assertEquals(task.description, taskRead.description)
+ assertEquals(task.startDate, taskRead.startDate)
+ assertEquals(task.status, taskRead.status)
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/io/ReadExampleUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/ReadExampleUnitTest.groovy
new file mode 100644
index 0000000000..bed77b4d81
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/io/ReadExampleUnitTest.groovy
@@ -0,0 +1,134 @@
+package com.baeldung.io
+
+import static org.junit.Assert.*
+import org.junit.Test
+
+class ReadExampleUnitTest {
+
+ @Test
+ void whenUsingEachLine_thenCorrectLinesReturned() {
+ def expectedList = [
+ 'First line of text',
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text']
+
+ def lines = []
+
+ new File('src/main/resources/ioInput.txt').eachLine { line ->
+ lines.add(line)
+ }
+ assertEquals(expectedList, lines)
+ }
+
+ @Test
+ void whenUsingReadEachLineWithLineNumber_thenCorrectLinesReturned() {
+ def expectedList = [
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text']
+
+ def lineNoRange = 2..4
+ def lines = []
+
+ new File('src/main/resources/ioInput.txt').eachLine { line, lineNo ->
+ if (lineNoRange.contains(lineNo)) {
+ lines.add(line)
+ }
+ }
+ assertEquals(expectedList, lines)
+ }
+
+ @Test
+ void whenUsingReadEachLineWithLineNumberStartAtZero_thenCorrectLinesReturned() {
+ def expectedList = [
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text']
+
+ def lineNoRange = 1..3
+ def lines = []
+
+ new File('src/main/resources/ioInput.txt').eachLine(0, { line, lineNo ->
+ if (lineNoRange.contains(lineNo)) {
+ lines.add(line)
+ }
+ })
+ assertEquals(expectedList, lines)
+ }
+
+ @Test
+ void whenUsingWithReader_thenLineCountReturned() {
+ def expectedCount = 4
+ def actualCount = 0
+ new File('src/main/resources/ioInput.txt').withReader { reader ->
+ while(reader.readLine()) {
+ actualCount++
+ }
+ }
+ assertEquals(expectedCount, actualCount)
+ }
+
+ @Test
+ void whenUsingNewReader_thenOutputFileCreated() {
+ def outputPath = 'src/main/resources/ioOut.txt'
+ def reader = new File('src/main/resources/ioInput.txt').newReader()
+ new File(outputPath).append(reader)
+ reader.close()
+ def ioOut = new File(outputPath)
+ assertTrue(ioOut.exists())
+ ioOut.delete()
+ }
+
+ @Test
+ void whenUsingWithInputStream_thenCorrectBytesAreReturned() {
+ def expectedLength = 1139
+ byte[] data = []
+ new File("src/main/resources/binaryExample.jpg").withInputStream { stream ->
+ data = stream.getBytes()
+ }
+ assertEquals(expectedLength, data.length)
+ }
+
+ @Test
+ void whenUsingNewInputStream_thenOutputFileCreated() {
+ def outputPath = 'src/main/resources/binaryOut.jpg'
+ def is = new File('src/main/resources/binaryExample.jpg').newInputStream()
+ new File(outputPath).append(is)
+ is.close()
+ def ioOut = new File(outputPath)
+ assertTrue(ioOut.exists())
+ ioOut.delete()
+ }
+
+ @Test
+ void whenUsingCollect_thenCorrectListIsReturned() {
+ def expectedList = ['First line of text', 'Second line of text', 'Third line of text', 'Fourth line of text']
+
+ def actualList = new File('src/main/resources/ioInput.txt').collect {it}
+ assertEquals(expectedList, actualList)
+ }
+
+ @Test
+ void whenUsingAsStringArray_thenCorrectArrayIsReturned() {
+ String[] expectedArray = ['First line of text', 'Second line of text', 'Third line of text', 'Fourth line of text']
+
+ def actualArray = new File('src/main/resources/ioInput.txt') as String[]
+ assertArrayEquals(expectedArray, actualArray)
+ }
+
+ @Test
+ void whenUsingText_thenCorrectStringIsReturned() {
+ def ln = System.getProperty('line.separator')
+ def expectedString = "First line of text${ln}Second line of text${ln}Third line of text${ln}Fourth line of text"
+ def actualString = new File('src/main/resources/ioInput.txt').text
+ assertEquals(expectedString.toString(), actualString)
+ }
+
+ @Test
+ void whenUsingBytes_thenByteArrayIsReturned() {
+ def expectedLength = 1139
+ def contents = new File('src/main/resources/binaryExample.jpg').bytes
+ assertEquals(expectedLength, contents.length)
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/io/TraverseFileTreeUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/TraverseFileTreeUnitTest.groovy
new file mode 100644
index 0000000000..dac0189fb9
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/io/TraverseFileTreeUnitTest.groovy
@@ -0,0 +1,61 @@
+package com.baeldung.io
+
+import org.junit.Test
+
+import groovy.io.FileType
+import groovy.io.FileVisitResult
+
+class TraverseFileTreeUnitTest {
+ @Test
+ void whenUsingEachFile_filesAreListed() {
+ new File('src/main/resources').eachFile { file ->
+ println file.name
+ }
+ }
+
+ @Test(expected = IllegalArgumentException)
+ void whenUsingEachFileOnAFile_anErrorOccurs() {
+ new File('src/main/resources/ioInput.txt').eachFile { file ->
+ println file.name
+ }
+ }
+
+ @Test
+ void whenUsingEachFileMatch_filesAreListed() {
+ new File('src/main/resources').eachFileMatch(~/io.*\.txt/) { file ->
+ println file.name
+ }
+ }
+
+ @Test
+ void whenUsingEachFileRecurse_thenFilesInSubfoldersAreListed() {
+ new File('src/main').eachFileRecurse(FileType.FILES) { file ->
+ println "$file.parent $file.name"
+ }
+ }
+
+ @Test
+ void whenUsingEachFileRecurse_thenDirsInSubfoldersAreListed() {
+ new File('src/main').eachFileRecurse(FileType.DIRECTORIES) { file ->
+ println "$file.parent $file.name"
+ }
+ }
+
+ @Test
+ void whenUsingEachDirRecurse_thenDirsAndSubDirsAreListed() {
+ new File('src/main').eachDirRecurse { dir ->
+ println "$dir.parent $dir.name"
+ }
+ }
+
+ @Test
+ void whenUsingTraverse_thenDirectoryIsTraversed() {
+ new File('src/main').traverse { file ->
+ if (file.directory && file.name == 'groovy') {
+ FileVisitResult.SKIP_SUBTREE
+ } else {
+ println "$file.parent - $file.name"
+ }
+ }
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/io/WriteExampleUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/WriteExampleUnitTest.groovy
new file mode 100644
index 0000000000..81758b430a
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/io/WriteExampleUnitTest.groovy
@@ -0,0 +1,96 @@
+package com.baeldung.io
+
+import static org.junit.Assert.*
+
+import org.junit.Before
+import org.junit.Test
+
+class WriteExampleUnitTest {
+ @Before
+ void clearOutputFile() {
+ new File('src/main/resources/ioOutput.txt').text = ''
+ new File('src/main/resources/ioBinaryOutput.bin').delete()
+ }
+
+ @Test
+ void whenUsingWithWriter_thenFileCreated() {
+ def outputLines = [
+ 'Line one of output example',
+ 'Line two of output example',
+ 'Line three of output example'
+ ]
+
+ def outputFileName = 'src/main/resources/ioOutput.txt'
+ new File(outputFileName).withWriter { writer ->
+ outputLines.each { line ->
+ writer.writeLine line
+ }
+ }
+ def writtenLines = new File(outputFileName).collect {it}
+ assertEquals(outputLines, writtenLines)
+ }
+
+ @Test
+ void whenUsingNewWriter_thenFileCreated() {
+ def outputLines = [
+ 'Line one of output example',
+ 'Line two of output example',
+ 'Line three of output example'
+ ]
+
+ def outputFileName = 'src/main/resources/ioOutput.txt'
+ def writer = new File(outputFileName).newWriter()
+ outputLines.forEach {line ->
+ writer.writeLine line
+ }
+ writer.flush()
+ writer.close()
+
+ def writtenLines = new File(outputFileName).collect {it}
+ assertEquals(outputLines, writtenLines)
+ }
+
+ @Test
+ void whenUsingDoubleLessThanOperator_thenFileCreated() {
+ def outputLines = [
+ 'Line one of output example',
+ 'Line two of output example',
+ 'Line three of output example'
+ ]
+
+ def ln = System.getProperty('line.separator')
+ def outputFileName = 'src/main/resources/ioOutput.txt'
+ new File(outputFileName) << "Line one of output example${ln}Line two of output example${ln}Line three of output example"
+ def writtenLines = new File(outputFileName).collect {it}
+ assertEquals(outputLines.size(), writtenLines.size())
+ }
+
+ @Test
+ void whenUsingBytes_thenBinaryFileCreated() {
+ def outputFileName = 'src/main/resources/ioBinaryOutput.bin'
+ def outputFile = new File(outputFileName)
+ byte[] outBytes = [44, 88, 22]
+ outputFile.bytes = outBytes
+ assertEquals(3, new File(outputFileName).size())
+ }
+
+ @Test
+ void whenUsingWithOutputStream_thenBinaryFileCreated() {
+ def outputFileName = 'src/main/resources/ioBinaryOutput.bin'
+ byte[] outBytes = [44, 88, 22]
+ new File(outputFileName).withOutputStream { stream ->
+ stream.write(outBytes)
+ }
+ assertEquals(3, new File(outputFileName).size())
+ }
+
+ @Test
+ void whenUsingNewOutputStream_thenBinaryFileCreated() {
+ def outputFileName = 'src/main/resources/ioBinaryOutput.bin'
+ byte[] outBytes = [44, 88, 22]
+ def os = new File(outputFileName).newOutputStream()
+ os.write(outBytes)
+ os.close()
+ assertEquals(3, new File(outputFileName).size())
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy
new file mode 100644
index 0000000000..f682503ed4
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy
@@ -0,0 +1,173 @@
+package com.baeldung.groovy.lists
+
+import static groovy.test.GroovyAssert.*
+import org.junit.Test
+
+class ListTest{
+
+ @Test
+ void testCreateList() {
+
+ def list = [1, 2, 3]
+ assertNotNull(list)
+
+ def listMix = ['A', "b", 1, true]
+ assertTrue(listMix == ['A', "b", 1, true])
+
+ def linkedList = [1, 2, 3] as LinkedList
+ assertTrue(linkedList instanceof LinkedList)
+
+ ArrayList arrList = [1, 2, 3]
+ assertTrue(arrList.class == ArrayList)
+
+ def copyList = new ArrayList(arrList)
+ assertTrue(copyList == arrList)
+
+ def cloneList = arrList.clone()
+ assertTrue(cloneList == arrList)
+ }
+
+ @Test
+ void testCreateEmptyList() {
+
+ def emptyList = []
+ assertTrue(emptyList.size() == 0)
+ }
+
+ @Test
+ void testCompareTwoLists() {
+
+ def list1 = [5, 6.0, 'p']
+ def list2 = [5, 6.0, 'p']
+ assertTrue(list1 == list2)
+ }
+
+ @Test
+ void testGetItemsFromList(){
+
+ def list = ["Hello", "World"]
+
+ assertTrue(list.get(1) == "World")
+ assertTrue(list[1] == "World")
+ assertTrue(list[-1] == "World")
+ assertTrue(list.getAt(1) == "World")
+ assertTrue(list.getAt(-2) == "Hello")
+ }
+
+ @Test
+ void testAddItemsToList() {
+
+ def list = []
+
+ list << 1
+ list.add("Apple")
+ assertTrue(list == [1, "Apple"])
+
+ list[2] = "Box"
+ list[4] = true
+ assertTrue(list == [1, "Apple", "Box", null, true])
+
+ list.add(1, 6.0)
+ assertTrue(list == [1, 6.0, "Apple", "Box", null, true])
+
+ def list2 = [1, 2]
+ list += list2
+ list += 12
+ assertTrue(list == [1, 6.0, "Apple", "Box", null, true, 1, 2, 12])
+ }
+
+ @Test
+ void testUpdateItemsInList() {
+
+ def list =[1, "Apple", 80, "App"]
+ list[1] = "Box"
+ list.set(2,90)
+ assertTrue(list == [1, "Box", 90, "App"])
+ }
+
+ @Test
+ void testRemoveItemsFromList(){
+
+ def list = [1, 2, 3, 4, 5, 5, 6, 6, 7]
+
+ list.remove(3)
+ assertTrue(list == [1, 2, 3, 5, 5, 6, 6, 7])
+
+ list.removeElement(5)
+ assertTrue(list == [1, 2, 3, 5, 6, 6, 7])
+
+ assertTrue(list - 6 == [1, 2, 3, 5, 7])
+ }
+
+ @Test
+ void testIteratingOnAList(){
+
+ def list = [1, "App", 3, 4]
+ list.each{ println it * 2}
+
+ list.eachWithIndex{ it, i -> println "$i : $it" }
+ }
+
+ @Test
+ void testCollectingToAnotherList(){
+
+ def list = ["Kay", "Henry", "Justin", "Tom"]
+ assertTrue(list.collect{"Hi " + it} == ["Hi Kay", "Hi Henry", "Hi Justin", "Hi Tom"])
+ }
+
+ @Test
+ void testJoinItemsInAList(){
+ assertTrue(["One", "Two", "Three"].join(",") == "One,Two,Three")
+ }
+
+ @Test
+ void testFilteringOnLists(){
+ def filterList = [2, 1, 3, 4, 5, 6, 76]
+
+ assertTrue(filterList.find{it > 3} == 4)
+
+ assertTrue(filterList.findAll{it > 3} == [4, 5, 6, 76])
+
+ assertTrue(filterList.findAll{ it instanceof Number} == [2, 1, 3, 4, 5, 6, 76])
+
+ assertTrue(filterList.grep( Number )== [2, 1, 3, 4, 5, 6, 76])
+
+ assertTrue(filterList.grep{ it> 6 }== [76])
+
+ def conditionList = [2, 1, 3, 4, 5, 6, 76]
+
+ assertFalse(conditionList.every{ it < 6})
+
+ assertTrue(conditionList.any{ it%2 == 0})
+
+ }
+
+ @Test
+ void testGetUniqueItemsInAList(){
+ assertTrue([1, 3, 3, 4].toUnique() == [1, 3, 4])
+
+ def uniqueList = [1, 3, 3, 4]
+ uniqueList.unique()
+ assertTrue(uniqueList == [1, 3, 4])
+
+ assertTrue(["A", "B", "Ba", "Bat", "Cat"].toUnique{ it.size()} == ["A", "Ba", "Bat"])
+ }
+
+ @Test
+ void testSorting(){
+
+ assertTrue([1, 2, 1, 0].sort() == [0, 1, 1, 2])
+ Comparator mc = {a,b -> a == b? 0: a < b? 1 : -1}
+
+ def list = [1, 2, 1, 0]
+ list.sort(mc)
+ assertTrue(list == [2, 1, 1, 0])
+
+ def strList = ["na", "ppp", "as"]
+ assertTrue(strList.max() == "ppp")
+
+ Comparator minc = {a,b -> a == b? 0: a < b? -1 : 1}
+ def numberList = [3, 2, 0, 7]
+ assertTrue(numberList.min(minc) == 0)
+ }
+}
\ No newline at end of file
diff --git a/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy
new file mode 100644
index 0000000000..97ffc50c76
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy
@@ -0,0 +1,85 @@
+package com.baeldung.map
+
+import static org.junit.Assert.*
+import org.junit.Test
+
+class MapUnitTest {
+
+ @Test
+ void whenUsingEach_thenMapIsIterated() {
+ def map = [
+ 'FF0000' : 'Red',
+ '00FF00' : 'Lime',
+ '0000FF' : 'Blue',
+ 'FFFF00' : 'Yellow'
+ ]
+
+ map.each { println "Hex Code: $it.key = Color Name: $it.value" }
+ }
+
+ @Test
+ void whenUsingEachWithEntry_thenMapIsIterated() {
+ def map = [
+ 'E6E6FA' : 'Lavender',
+ 'D8BFD8' : 'Thistle',
+ 'DDA0DD' : 'Plum',
+ ]
+
+ map.each { entry -> println "Hex Code: $entry.key = Color Name: $entry.value" }
+ }
+
+ @Test
+ void whenUsingEachWithKeyAndValue_thenMapIsIterated() {
+ def map = [
+ '000000' : 'Black',
+ 'FFFFFF' : 'White',
+ '808080' : 'Gray'
+ ]
+
+ map.each { key, val ->
+ println "Hex Code: $key = Color Name $val"
+ }
+ }
+
+ @Test
+ void whenUsingEachWithIndexAndEntry_thenMapIsIterated() {
+ def map = [
+ '800080' : 'Purple',
+ '4B0082' : 'Indigo',
+ '6A5ACD' : 'Slate Blue'
+ ]
+
+ map.eachWithIndex { entry, index ->
+ def indent = ((index == 0 || index % 2 == 0) ? " " : "")
+ println "$indent Hex Code: $entry.key = Color Name: $entry.value"
+ }
+ }
+
+ @Test
+ void whenUsingEachWithIndexAndKeyAndValue_thenMapIsIterated() {
+ def map = [
+ 'FFA07A' : 'Light Salmon',
+ 'FF7F50' : 'Coral',
+ 'FF6347' : 'Tomato',
+ 'FF4500' : 'Orange Red'
+ ]
+
+ map.eachWithIndex { key, val, index ->
+ def indent = ((index == 0 || index % 2 == 0) ? " " : "")
+ println "$indent Hex Code: $key = Color Name: $val"
+ }
+ }
+
+ @Test
+ void whenUsingForLoop_thenMapIsIterated() {
+ def map = [
+ '2E8B57' : 'Seagreen',
+ '228B22' : 'Forest Green',
+ '008000' : 'Green'
+ ]
+
+ for (entry in map) {
+ println "Hex Code: $entry.key = Color Name: $entry.value"
+ }
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy b/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy
new file mode 100644
index 0000000000..3ef4a5d460
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy
@@ -0,0 +1,101 @@
+import com.baeldung.strings.Concatenate;
+
+class ConcatenateTest extends GroovyTestCase {
+
+ void testSimpleConcat() {
+ def name = new Concatenate()
+ name.first = 'Joe';
+ name.last = 'Smith';
+ def expected = 'My name is Joe Smith'
+ assertToString(name.doSimpleConcat(), expected)
+ }
+
+ void testConcatUsingGString() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingGString(), expected)
+ }
+
+ void testConcatUsingGStringClosures() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingGStringClosures(), expected)
+ }
+
+ void testConcatUsingStringConcatMethod() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingStringConcatMethod(), expected)
+ }
+
+ void testConcatUsingLeftShiftOperator() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingLeftShiftOperator(), expected)
+ }
+
+ void testConcatUsingArrayJoinMethod() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingArrayJoinMethod(), expected)
+ }
+
+ void testConcatUsingArrayInjectMethod() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingArrayInjectMethod(), expected)
+ }
+
+ void testConcatUsingStringBuilder() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingStringBuilder(), expected)
+ }
+
+ void testConcatUsingStringBuffer() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingStringBuffer(), expected)
+ }
+
+ void testConcatMultilineUsingStringConcatMethod() {
+ def name = new Concatenate()
+ name.first = '''Joe
+ Smith
+ ''';
+ name.last = 'Junior';
+ def expected = '''My name is Joe
+ Smith
+ Junior''';
+ assertToString(name.doConcatUsingStringConcatMethod(), expected)
+ }
+
+ void testGStringvsClosure(){
+ def first = "Joe";
+ def last = "Smith";
+ def eagerGString = "My name is $first $last"
+ def lazyGString = "My name is ${-> first} ${-> last}"
+
+ assert eagerGString == "My name is Joe Smith"
+ assert lazyGString == "My name is Joe Smith"
+ first = "David";
+ assert eagerGString == "My name is Joe Smith"
+ assert lazyGString == "My name is David Smith"
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy
new file mode 100644
index 0000000000..c043723d95
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy
@@ -0,0 +1,19 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class CharacterInGroovy {
+
+ @Test
+ void 'character'() {
+ char a = 'A' as char
+ char b = 'B' as char
+ char c = (char) 'C'
+
+ Assert.assertTrue(a instanceof Character)
+ Assert.assertTrue(b instanceof Character)
+ Assert.assertTrue(c instanceof Character)
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/DollarSlashyString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DollarSlashyString.groovy
new file mode 100644
index 0000000000..db8ba68c8f
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DollarSlashyString.groovy
@@ -0,0 +1,24 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Test
+
+class DollarSlashyString {
+
+ @Test
+ void 'dollar slashy string'() {
+ def name = "John"
+
+ def dollarSlashy = $/
+ Hello $name!,
+
+ I can show you $ sign or escaped dollar sign: $$
+ Both slashes works: \ or /, but we can still escape it: $/
+
+ We have to escape opening and closing delimiter:
+ - $$$/
+ - $/$$
+ /$
+
+ print(dollarSlashy)
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy
new file mode 100644
index 0000000000..a730244d0a
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy
@@ -0,0 +1,67 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class DoubleQuotedString {
+
+ @Test
+ void 'escape double quoted string'() {
+ def example = "Hello \"world\"!"
+
+ println(example)
+ }
+
+ @Test
+ void 'String ang GString'() {
+ def string = "example"
+ def stringWithExpression = "example${2}"
+
+ Assert.assertTrue(string instanceof String)
+ Assert.assertTrue(stringWithExpression instanceof GString)
+ Assert.assertTrue(stringWithExpression.toString() instanceof String)
+ }
+
+ @Test
+ void 'placeholder with variable'() {
+ def name = "John"
+ def helloName = "Hello $name!".toString()
+
+ Assert.assertEquals("Hello John!", helloName)
+ }
+
+ @Test
+ void 'placeholder with expression'() {
+ def result = "result is ${2 * 2}".toString()
+
+ Assert.assertEquals("result is 4", result)
+ }
+
+ @Test
+ void 'placeholder with dotted access'() {
+ def person = [name: 'John']
+
+ def myNameIs = "I'm $person.name, and you?".toString()
+
+ Assert.assertEquals("I'm John, and you?", myNameIs)
+ }
+
+ @Test
+ void 'placeholder with method call'() {
+ def name = 'John'
+
+ def result = "Uppercase name: ${name.toUpperCase()}".toString()
+
+ Assert.assertEquals("Uppercase name: JOHN", result)
+ }
+
+
+ @Test
+ void 'GString and String hashcode'() {
+ def string = "2+2 is 4"
+ def gstring = "2+2 is ${4}"
+
+ Assert.assertTrue(string.hashCode() != gstring.hashCode())
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy
new file mode 100644
index 0000000000..569991b788
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy
@@ -0,0 +1,15 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class SingleQuotedString {
+
+ @Test
+ void 'single quoted string'() {
+ def example = 'Hello world'
+
+ Assert.assertEquals('Hello world!', 'Hello' + ' world!')
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/SlashyString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SlashyString.groovy
new file mode 100644
index 0000000000..09ba35e17e
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SlashyString.groovy
@@ -0,0 +1,31 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class SlashyString {
+
+ @Test
+ void 'slashy string'() {
+ def pattern = /.*foobar.*\/hello.*/
+
+ Assert.assertTrue("I'm matching foobar /hello regexp pattern".matches(pattern))
+ }
+
+ void 'wont compile'() {
+// if ('' == //) {
+// println("I can't compile")
+// }
+ }
+
+ @Test
+ void 'interpolate and multiline'() {
+ def name = 'John'
+
+ def example = /
+ Hello $name
+ second line
+ /
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy
new file mode 100644
index 0000000000..e45f352285
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy
@@ -0,0 +1,26 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class Strings {
+
+ @Test
+ void 'string interpolation '() {
+ def name = "Kacper"
+
+ def result = "Hello ${name}!"
+
+ Assert.assertEquals("Hello Kacper!", result.toString())
+ }
+
+ @Test
+ void 'string concatenation'() {
+ def first = "first"
+ def second = "second"
+
+ def concatenation = first + second
+
+ Assert.assertEquals("firstsecond", concatenation)
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleDoubleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleDoubleQuotedString.groovy
new file mode 100644
index 0000000000..cbbb1a4665
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleDoubleQuotedString.groovy
@@ -0,0 +1,19 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Test
+
+class TripleDoubleQuotedString {
+
+ @Test
+ void 'triple-quoted strings with interpolation'() {
+ def name = "John"
+
+ def multiLine = """
+ I'm $name.
+ "This is quotation"
+ """
+
+ println(multiLine)
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleSingleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleSingleQuotedString.groovy
new file mode 100644
index 0000000000..24d55b8a2a
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleSingleQuotedString.groovy
@@ -0,0 +1,67 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class TripleSingleQuotedString {
+
+ def 'formatted json'() {
+ def jsonContent = '''
+ {
+ "name": "John",
+ "age": 20,
+ "birthDate": null
+ }
+ '''
+ }
+
+ def 'triple single quoted'() {
+ def triple = '''im triple single quoted string'''
+ }
+
+ @Test
+ void 'triple single quoted with multiline string'() {
+ def triple = '''
+ firstline
+ secondline
+ '''
+
+ Assert.assertTrue(triple.startsWith("\n"))
+ }
+
+ @Test
+ void 'triple single quoted with multiline string with stripIndent() and removing newline characters'() {
+ def triple = '''\
+ firstline
+ secondline'''.stripIndent()
+
+ Assert.assertEquals("firstline\nsecondline", triple)
+ }
+
+ @Test
+ void 'triple single quoted with multiline string with last line with only whitespaces'() {
+ def triple = '''\
+ firstline
+ secondline\
+ '''.stripIndent()
+
+ println(triple)
+ }
+
+ @Test
+ void 'triple single quoted with multiline string with stripMargin(Character) and removing newline characters'() {
+ def triple = '''\
+ |firstline
+ |secondline'''.stripMargin()
+
+ println(triple)
+ }
+
+ @Test
+ void 'striple single quoted with special characters'() {
+ def specialCharacters = '''hello \'John\'. This is backslash - \\. \nSecond line starts here'''
+
+ println(specialCharacters)
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy
new file mode 100644
index 0000000000..85130e8f07
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy
@@ -0,0 +1,114 @@
+package com.baeldung.traits
+
+import spock.lang.Specification
+
+class TraitsUnitTest extends Specification {
+
+ Employee employee
+ Dog dog
+
+ void setup () {
+ employee = new Employee()
+ dog = new Dog()
+ }
+
+ def 'Should return msg string when using Employee.sayHello method provided by UserTrait' () {
+ when:
+ def msg = employee.sayHello()
+ then:
+ msg
+ msg instanceof String
+ assert msg == "Hello!"
+ }
+
+ def 'Should return displayMsg string when using Employee.showName method' () {
+ when:
+ def displayMsg = employee.showName()
+ then:
+ displayMsg
+ displayMsg instanceof String
+ assert displayMsg == "Hello, Bob!"
+ }
+
+ def 'Should return greetMsg string when using Employee.greet method' () {
+ when:
+ def greetMsg = employee.greet()
+ then:
+ greetMsg
+ greetMsg instanceof String
+ assert greetMsg == "Hello, from a private method!"
+ }
+
+ def 'Should return MissingMethodException when using Employee.greetingMessage method' () {
+ when:
+ def exception
+ try {
+ employee.greetingMessage()
+ }catch(Exception e) {
+ exception = e
+ }
+
+ then:
+ exception
+ exception instanceof groovy.lang.MissingMethodException
+ assert exception.message == "No signature of method: com.baeldung.traits.Employee.greetingMessage()"+
+ " is applicable for argument types: () values: []"
+ }
+
+ def 'Should return employee instance when using Employee.whoAmI method' () {
+ when:
+ def emp = employee.self()
+ then:
+ emp
+ emp instanceof Employee
+ assert emp.is(employee)
+ }
+
+ def 'Should display lastName when using Employee.showLastName method' () {
+ when:
+ def lastNameMsg = employee.showLastName()
+ then:
+ lastNameMsg
+ lastNameMsg instanceof String
+ assert lastNameMsg == "Hello, Marley!"
+ }
+
+ def 'Should be able to define properties of UserTrait in Employee instance' () {
+ when:
+ employee = new Employee(email: "a@e.com", address: "baeldung.com")
+ then:
+ employee
+ employee instanceof Employee
+ assert employee.email == "a@e.com"
+ assert employee.address == "baeldung.com"
+ }
+
+ def 'Should execute basicAbility method from SpeakingTrait and return msg string' () {
+ when:
+ def speakMsg = dog.basicAbility()
+ then:
+ speakMsg
+ speakMsg instanceof String
+ assert speakMsg == "Speaking!!"
+ }
+
+ def 'Should verify multiple inheritance with traits and execute overridden traits method' () {
+ when:
+ def walkSpeakMsg = dog.speakAndWalk()
+ println walkSpeakMsg
+ then:
+ walkSpeakMsg
+ walkSpeakMsg instanceof String
+ assert walkSpeakMsg == "Walk and speak!!"
+ }
+
+ def 'Should implement AnimalTrait at runtime and access basicBehavior method' () {
+ when:
+ def dogInstance = new Dog() as AnimalTrait
+ def basicBehaviorMsg = dogInstance.basicBehavior()
+ then:
+ basicBehaviorMsg
+ basicBehaviorMsg instanceof String
+ assert basicBehaviorMsg == "Animalistic!!"
+ }
+}
\ No newline at end of file
diff --git a/core-java-10/pom.xml b/core-java-10/pom.xml
index 9fcdd9a162..b15f8b5d63 100644
--- a/core-java-10/pom.xml
+++ b/core-java-10/pom.xml
@@ -3,9 +3,9 @@
4.0.0
com.baeldung
core-java-10
- jar
0.1.0-SNAPSHOT
core-java-10
+ jar
http://maven.apache.org
diff --git a/core-java-11/README.md b/core-java-11/README.md
index c8039f4bc5..3c8b94fa28 100644
--- a/core-java-11/README.md
+++ b/core-java-11/README.md
@@ -3,3 +3,4 @@
- [Java 11 Single File Source Code](https://www.baeldung.com/java-single-file-source-code)
- [Java 11 Local Variable Syntax for Lambda Parameters](https://www.baeldung.com/java-var-lambda-params)
- [Java 11 String API Additions](https://www.baeldung.com/java-11-string-api)
+- [Java 11 Nest Based Access Control](https://www.baeldung.com/java-nest-based-access-control)
diff --git a/core-java-11/pom.xml b/core-java-11/pom.xml
index 4dcab49867..a9776d8f3b 100644
--- a/core-java-11/pom.xml
+++ b/core-java-11/pom.xml
@@ -3,9 +3,9 @@
4.0.0
com.baeldung
core-java-11
- jar
0.1.0-SNAPSHOT
core-java-11
+ jar
http://maven.apache.org
diff --git a/core-java-11/src/main/java/com/baeldung/epsilongc/MemoryPolluter.java b/core-java-11/src/main/java/com/baeldung/epsilongc/MemoryPolluter.java
new file mode 100644
index 0000000000..97e216513b
--- /dev/null
+++ b/core-java-11/src/main/java/com/baeldung/epsilongc/MemoryPolluter.java
@@ -0,0 +1,18 @@
+package com.baeldung.epsilongc;
+
+public class MemoryPolluter {
+
+ private static final int MEGABYTE_IN_BYTES = 1024 * 1024;
+ private static final int ITERATION_COUNT = 1024 * 10;
+
+ public static void main(String[] args) {
+ System.out.println("Starting pollution");
+
+ for (int i = 0; i < ITERATION_COUNT; i++) {
+ byte[] array = new byte[MEGABYTE_IN_BYTES];
+ }
+
+ System.out.println("Terminating");
+ }
+
+}
diff --git a/core-java-11/src/main/java/com/baeldung/java11/httpclient/HttpClientExample.java b/core-java-11/src/main/java/com/baeldung/java11/httpclient/HttpClientExample.java
new file mode 100644
index 0000000000..fb4abd3bb6
--- /dev/null
+++ b/core-java-11/src/main/java/com/baeldung/java11/httpclient/HttpClientExample.java
@@ -0,0 +1,132 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.baeldung.java11.httpclient;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpClient.Version;
+import java.net.http.HttpRequest;
+import java.net.http.HttpRequest.BodyPublishers;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.net.http.HttpResponse.PushPromiseHandler;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class HttpClientExample {
+
+ public static void main(String[] args) throws Exception {
+ httpGetRequest();
+ httpPostRequest();
+ asynchronousGetRequest();
+ asynchronousMultipleRequests();
+ pushRequest();
+ }
+
+ public static void httpGetRequest() throws URISyntaxException, IOException, InterruptedException {
+ HttpClient client = HttpClient.newHttpClient();
+ HttpRequest request = HttpRequest.newBuilder()
+ .version(HttpClient.Version.HTTP_2)
+ .uri(URI.create("http://jsonplaceholder.typicode.com/posts/1"))
+ .headers("Accept-Enconding", "gzip, deflate")
+ .build();
+ HttpResponse response = client.send(request, BodyHandlers.ofString());
+
+ String responseBody = response.body();
+ int responseStatusCode = response.statusCode();
+
+ System.out.println("httpGetRequest: " + responseBody);
+ System.out.println("httpGetRequest status code: " + responseStatusCode);
+ }
+
+ public static void httpPostRequest() throws URISyntaxException, IOException, InterruptedException {
+ HttpClient client = HttpClient.newBuilder()
+ .version(HttpClient.Version.HTTP_2)
+ .build();
+ HttpRequest request = HttpRequest.newBuilder(new URI("http://jsonplaceholder.typicode.com/posts"))
+ .version(HttpClient.Version.HTTP_2)
+ .POST(BodyPublishers.ofString("Sample Post Request"))
+ .build();
+ HttpResponse response = client.send(request, BodyHandlers.ofString());
+ String responseBody = response.body();
+ System.out.println("httpPostRequest : " + responseBody);
+ }
+
+ public static void asynchronousGetRequest() throws URISyntaxException {
+ HttpClient client = HttpClient.newHttpClient();
+ URI httpURI = new URI("http://jsonplaceholder.typicode.com/posts/1");
+ HttpRequest request = HttpRequest.newBuilder(httpURI)
+ .version(HttpClient.Version.HTTP_2)
+ .build();
+ CompletableFuture futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
+ .thenAccept(resp -> {
+ System.out.println("Got pushed response " + resp.uri());
+ System.out.println("Response statuscode: " + resp.statusCode());
+ System.out.println("Response body: " + resp.body());
+ });
+ System.out.println("futureResponse" + futureResponse);
+
+ }
+
+ public static void asynchronousMultipleRequests() throws URISyntaxException {
+ HttpClient client = HttpClient.newHttpClient();
+ List uris = Arrays.asList(new URI("http://jsonplaceholder.typicode.com/posts/1"), new URI("http://jsonplaceholder.typicode.com/posts/2"));
+ List requests = uris.stream()
+ .map(HttpRequest::newBuilder)
+ .map(reqBuilder -> reqBuilder.build())
+ .collect(Collectors.toList());
+ System.out.println("Got pushed response1 " + requests);
+ CompletableFuture.allOf(requests.stream()
+ .map(request -> client.sendAsync(request, BodyHandlers.ofString()))
+ .toArray(CompletableFuture>[]::new))
+ .thenAccept(System.out::println)
+ .join();
+ }
+
+ public static void pushRequest() throws URISyntaxException, InterruptedException {
+ System.out.println("Running HTTP/2 Server Push example...");
+
+ HttpClient httpClient = HttpClient.newBuilder()
+ .version(Version.HTTP_2)
+ .build();
+
+ HttpRequest pageRequest = HttpRequest.newBuilder()
+ .uri(URI.create("https://http2.golang.org/serverpush"))
+ .build();
+
+ // Interface HttpResponse.PushPromiseHandler
+ // void applyPushPromise(HttpRequest initiatingRequest, HttpRequest pushPromiseRequest, Function,CompletableFuture>> acceptor)
+ httpClient.sendAsync(pageRequest, BodyHandlers.ofString(), pushPromiseHandler())
+ .thenAccept(pageResponse -> {
+ System.out.println("Page response status code: " + pageResponse.statusCode());
+ System.out.println("Page response headers: " + pageResponse.headers());
+ String responseBody = pageResponse.body();
+ System.out.println(responseBody);
+ }).join();
+
+ Thread.sleep(1000); // waiting for full response
+ }
+
+ private static PushPromiseHandler pushPromiseHandler() {
+ return (HttpRequest initiatingRequest,
+ HttpRequest pushPromiseRequest,
+ Function,
+ CompletableFuture>> acceptor) -> {
+ acceptor.apply(BodyHandlers.ofString())
+ .thenAccept(resp -> {
+ System.out.println(" Pushed response: " + resp.uri() + ", headers: " + resp.headers());
+ });
+ System.out.println("Promise request: " + pushPromiseRequest.uri());
+ System.out.println("Promise request: " + pushPromiseRequest.headers());
+ };
+ }
+
+}
diff --git a/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientTest.java b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientTest.java
new file mode 100644
index 0000000000..bade666636
--- /dev/null
+++ b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientTest.java
@@ -0,0 +1,240 @@
+package com.baeldung.java11.httpclient.test;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.net.Authenticator;
+import java.net.CookieManager;
+import java.net.CookiePolicy;
+import java.net.HttpURLConnection;
+import java.net.PasswordAuthentication;
+import java.net.ProxySelector;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Test;
+
+public class HttpClientTest {
+
+ @Test
+ public void shouldReturnSampleDataContentWhenConnectViaSystemProxy() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofString("Sample body"))
+ .build();
+
+
+ HttpResponse response = HttpClient.newBuilder()
+ .proxy(ProxySelector.getDefault())
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.body(), containsString("Sample body"));
+ }
+
+ @Test
+ public void shouldNotFollowRedirectWhenSetToDefaultNever() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("http://stackoverflow.com"))
+ .version(HttpClient.Version.HTTP_1_1)
+ .GET()
+ .build();
+ HttpResponse response = HttpClient.newBuilder()
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_MOVED_PERM));
+ assertThat(response.body(), containsString("https://stackoverflow.com/"));
+ }
+
+ @Test
+ public void shouldFollowRedirectWhenSetToAlways() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("http://stackoverflow.com"))
+ .version(HttpClient.Version.HTTP_1_1)
+ .GET()
+ .build();
+ HttpResponse response = HttpClient.newBuilder()
+ .followRedirects(HttpClient.Redirect.ALWAYS)
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.request()
+ .uri()
+ .toString(), equalTo("https://stackoverflow.com/"));
+ }
+
+ @Test
+ public void shouldReturnOKStatusForAuthenticatedAccess() throws URISyntaxException, IOException, InterruptedException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/basic-auth"))
+ .GET()
+ .build();
+ HttpResponse response = HttpClient.newBuilder()
+ .authenticator(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication("postman", "password".toCharArray());
+ }
+ })
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldSendRequestAsync() throws URISyntaxException, InterruptedException, ExecutionException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofString("Sample body"))
+ .build();
+ CompletableFuture> response = HttpClient.newBuilder()
+ .build()
+ .sendAsync(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.get()
+ .statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldUseJustTwoThreadWhenProcessingSendAsyncRequest() throws URISyntaxException, InterruptedException, ExecutionException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .GET()
+ .build();
+
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+
+ CompletableFuture> response1 = HttpClient.newBuilder()
+ .executor(executorService)
+ .build()
+ .sendAsync(request, HttpResponse.BodyHandlers.ofString());
+
+ CompletableFuture> response2 = HttpClient.newBuilder()
+ .executor(executorService)
+ .build()
+ .sendAsync(request, HttpResponse.BodyHandlers.ofString());
+
+ CompletableFuture> response3 = HttpClient.newBuilder()
+ .executor(executorService)
+ .build()
+ .sendAsync(request, HttpResponse.BodyHandlers.ofString());
+
+ CompletableFuture.allOf(response1, response2, response3)
+ .join();
+
+ assertThat(response1.get()
+ .statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response2.get()
+ .statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response3.get()
+ .statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldNotStoreCookieWhenPolicyAcceptNone() throws URISyntaxException, IOException, InterruptedException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .GET()
+ .build();
+
+ HttpClient httpClient = HttpClient.newBuilder()
+ .cookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_NONE))
+ .build();
+
+ httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertTrue(httpClient.cookieHandler()
+ .isPresent());
+ }
+
+ @Test
+ public void shouldStoreCookieWhenPolicyAcceptAll() throws URISyntaxException, IOException, InterruptedException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .GET()
+ .build();
+
+ HttpClient httpClient = HttpClient.newBuilder()
+ .cookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ALL))
+ .build();
+
+ httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertTrue(httpClient.cookieHandler()
+ .isPresent());
+ }
+
+ @Test
+ public void shouldProcessMultipleRequestViaStream() throws URISyntaxException, ExecutionException, InterruptedException {
+ List targets = Arrays.asList(new URI("https://postman-echo.com/get?foo1=bar1"), new URI("https://postman-echo.com/get?foo2=bar2"));
+
+ HttpClient client = HttpClient.newHttpClient();
+
+ List> futures = targets.stream()
+ .map(target -> client.sendAsync(HttpRequest.newBuilder(target)
+ .GET()
+ .build(), HttpResponse.BodyHandlers.ofString())
+ .thenApply(response -> response.body()))
+ .collect(Collectors.toList());
+
+ CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
+ .join();
+
+ if (futures.get(0)
+ .get()
+ .contains("foo1")) {
+ assertThat(futures.get(0)
+ .get(), containsString("bar1"));
+ assertThat(futures.get(1)
+ .get(), containsString("bar2"));
+ } else {
+ assertThat(futures.get(1)
+ .get(), containsString("bar2"));
+ assertThat(futures.get(1)
+ .get(), containsString("bar1"));
+ }
+
+ }
+
+ @Test
+ public void completeExceptionallyExample() {
+ CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(String::toUpperCase,
+ CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));
+ CompletableFuture exceptionHandler = cf.handle((s, th) -> { return (th != null) ? "message upon cancel" : ""; });
+ cf.completeExceptionally(new RuntimeException("completed exceptionally"));
+ assertTrue("Was not completed exceptionally", cf.isCompletedExceptionally());
+ try {
+ cf.join();
+ fail("Should have thrown an exception");
+ } catch (CompletionException ex) { // just for testing
+ assertEquals("completed exceptionally", ex.getCause().getMessage());
+ }
+
+ assertEquals("message upon cancel", exceptionHandler.join());
+ }
+
+}
diff --git a/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestTest.java b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestTest.java
new file mode 100644
index 0000000000..7d138bd8d5
--- /dev/null
+++ b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestTest.java
@@ -0,0 +1,168 @@
+package com.baeldung.java11.httpclient.test;
+
+import static java.time.temporal.ChronoUnit.SECONDS;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.file.Paths;
+import java.security.NoSuchAlgorithmException;
+import java.time.Duration;
+
+import org.junit.Test;
+
+public class HttpRequestTest {
+
+ @Test
+ public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .GET()
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldUseHttp2WhenWebsiteUsesHttp2() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://stackoverflow.com"))
+ .version(HttpClient.Version.HTTP_2)
+ .GET()
+ .build();
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.version(), equalTo(HttpClient.Version.HTTP_2));
+ }
+
+ @Test
+ public void shouldFallbackToHttp1_1WhenWebsiteDoesNotUseHttp2() throws IOException, InterruptedException, URISyntaxException, NoSuchAlgorithmException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .version(HttpClient.Version.HTTP_2)
+ .GET()
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.version(), equalTo(HttpClient.Version.HTTP_1_1));
+ }
+
+ @Test
+ public void shouldReturnStatusOKWhenSendGetRequestWithDummyHeaders() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .headers("key1", "value1", "key2", "value2")
+ .GET()
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldReturnStatusOKWhenSendGetRequestTimeoutSet() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .timeout(Duration.of(10, SECONDS))
+ .GET()
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldReturnNoContentWhenPostWithNoBody() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .POST(HttpRequest.BodyPublishers.noBody())
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldReturnSampleDataContentWhenPostWithBodyText() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofString("Sample request body"))
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.body(), containsString("Sample request body"));
+ }
+
+ @Test
+ public void shouldReturnSampleDataContentWhenPostWithInputStream() throws IOException, InterruptedException, URISyntaxException {
+ byte[] sampleData = "Sample request body".getBytes();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofInputStream(() -> new ByteArrayInputStream(sampleData)))
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.body(), containsString("Sample request body"));
+ }
+
+ @Test
+ public void shouldReturnSampleDataContentWhenPostWithByteArrayProcessorStream() throws IOException, InterruptedException, URISyntaxException {
+ byte[] sampleData = "Sample request body".getBytes();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofByteArray(sampleData))
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.body(), containsString("Sample request body"));
+ }
+
+ @Test
+ public void shouldReturnSampleDataContentWhenPostWithFileProcessorStream() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofFile(Paths.get("src/test/resources/sample.txt")))
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.body(), containsString("Sample file content"));
+ }
+
+}
diff --git a/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseTest.java b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseTest.java
new file mode 100644
index 0000000000..78d86fbf4e
--- /dev/null
+++ b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseTest.java
@@ -0,0 +1,54 @@
+package com.baeldung.java11.httpclient.test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+
+import org.junit.Test;
+
+public class HttpResponseTest {
+
+ @Test
+ public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .version(HttpClient.Version.HTTP_2)
+ .GET()
+ .build();
+
+ HttpResponse response = HttpClient.newBuilder()
+ .followRedirects(HttpClient.Redirect.NORMAL)
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertNotNull(response.body());
+ }
+
+ @Test
+ public void shouldResponseURIDifferentThanRequestUIRWhenRedirect() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("http://stackoverflow.com"))
+ .version(HttpClient.Version.HTTP_2)
+ .GET()
+ .build();
+ HttpResponse response = HttpClient.newBuilder()
+ .followRedirects(HttpClient.Redirect.NORMAL)
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(request.uri()
+ .toString(), equalTo("http://stackoverflow.com"));
+ assertThat(response.uri()
+ .toString(), equalTo("https://stackoverflow.com/"));
+ }
+
+}
diff --git a/core-java-8/README.md b/core-java-8/README.md
index 892dc71f76..99182da390 100644
--- a/core-java-8/README.md
+++ b/core-java-8/README.md
@@ -4,9 +4,9 @@
### Relevant Articles:
- [Java 8 Collectors](http://www.baeldung.com/java-8-collectors)
-- [Guide to Java 8’s Functional Interfaces](http://www.baeldung.com/java-8-functional-interfaces)
+- [Functional Interfaces in Java 8](http://www.baeldung.com/java-8-functional-interfaces)
- [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda)
-- [Java 8 New Features](http://www.baeldung.com/java-8-new-features)
+- [New Features in Java 8](http://www.baeldung.com/java-8-new-features)
- [Lambda Expressions and Functional Interfaces: Tips and Best Practices](http://www.baeldung.com/java-8-lambda-expressions-tips)
- [The Double Colon Operator in Java 8](http://www.baeldung.com/java-8-double-colon-operator)
- [Guide to Java 8 groupingBy Collector](http://www.baeldung.com/java-groupingby-collector)
@@ -38,3 +38,5 @@
- [Java @SafeVarargs Annotation](https://www.baeldung.com/java-safevarargs)
- [Java @Deprecated Annotation](https://www.baeldung.com/java-deprecated)
- [Java 8 Predicate Chain](https://www.baeldung.com/java-predicate-chain)
+- [Method References in Java](https://www.baeldung.com/java-method-references)
+- [Creating a Custom Annotation in Java](https://www.baeldung.com/java-custom-annotation)
diff --git a/core-java-8/pom.xml b/core-java-8/pom.xml
index 112e8b764d..b63afef7d4 100644
--- a/core-java-8/pom.xml
+++ b/core-java-8/pom.xml
@@ -4,8 +4,8 @@
com.baeldung
core-java-8
0.1.0-SNAPSHOT
- jar
core-java-8
+ jar
com.baeldung
@@ -180,7 +180,6 @@
4.1
4.01
1.10
- 1.16.12
0.9.0
1.13
2.10
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/Init.java b/core-java-8/src/main/java/com/baeldung/customannotations/Init.java
new file mode 100644
index 0000000000..265e7ba1d6
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/Init.java
@@ -0,0 +1,13 @@
+package com.baeldung.customannotations;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target(METHOD)
+public @interface Init {
+
+}
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/JsonElement.java b/core-java-8/src/main/java/com/baeldung/customannotations/JsonElement.java
new file mode 100644
index 0000000000..e41a5b1e30
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/JsonElement.java
@@ -0,0 +1,13 @@
+package com.baeldung.customannotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target({ FIELD })
+public @interface JsonElement {
+ public String key() default "";
+}
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializable.java b/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializable.java
new file mode 100644
index 0000000000..48eeb09a1b
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializable.java
@@ -0,0 +1,13 @@
+package com.baeldung.customannotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target(TYPE)
+public @interface JsonSerializable {
+
+}
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializationException.java b/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializationException.java
new file mode 100644
index 0000000000..f2c29855ac
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializationException.java
@@ -0,0 +1,10 @@
+package com.baeldung.customannotations;
+
+public class JsonSerializationException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public JsonSerializationException(String message) {
+ super(message);
+ }
+}
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java b/core-java-8/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java
new file mode 100644
index 0000000000..dd126be8ed
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java
@@ -0,0 +1,67 @@
+package com.baeldung.customannotations;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class ObjectToJsonConverter {
+ public String convertToJson(Object object) throws JsonSerializationException {
+ try {
+
+ checkIfSerializable(object);
+ initializeObject(object);
+ return getJsonString(object);
+
+ } catch (Exception e) {
+ throw new JsonSerializationException(e.getMessage());
+ }
+ }
+
+ private void checkIfSerializable(Object object) {
+ if (Objects.isNull(object)) {
+ throw new JsonSerializationException("Can't serialize a null object");
+ }
+
+ Class> clazz = object.getClass();
+ if (!clazz.isAnnotationPresent(JsonSerializable.class)) {
+ throw new JsonSerializationException("The class " + clazz.getSimpleName() + " is not annotated with JsonSerializable");
+ }
+ }
+
+ private void initializeObject(Object object) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ Class> clazz = object.getClass();
+ for (Method method : clazz.getDeclaredMethods()) {
+ if (method.isAnnotationPresent(Init.class)) {
+ method.setAccessible(true);
+ method.invoke(object);
+ }
+ }
+ }
+
+ private String getJsonString(Object object) throws IllegalArgumentException, IllegalAccessException {
+ Class> clazz = object.getClass();
+ Map jsonElementsMap = new HashMap<>();
+ for (Field field : clazz.getDeclaredFields()) {
+ field.setAccessible(true);
+ if (field.isAnnotationPresent(JsonElement.class)) {
+ jsonElementsMap.put(getKey(field), (String) field.get(object));
+ }
+ }
+
+ String jsonString = jsonElementsMap.entrySet()
+ .stream()
+ .map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"")
+ .collect(Collectors.joining(","));
+ return "{" + jsonString + "}";
+ }
+
+ private String getKey(Field field) {
+ String value = field.getAnnotation(JsonElement.class)
+ .key();
+ return value.isEmpty() ? field.getName() : value;
+ }
+}
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/Person.java b/core-java-8/src/main/java/com/baeldung/customannotations/Person.java
new file mode 100644
index 0000000000..5db1a7f279
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/Person.java
@@ -0,0 +1,66 @@
+package com.baeldung.customannotations;
+
+@JsonSerializable
+public class Person {
+ @JsonElement
+ private String firstName;
+ @JsonElement
+ private String lastName;
+ @JsonElement(key = "personAge")
+ private String age;
+
+ private String address;
+
+ public Person(String firstName, String lastName) {
+ super();
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ public Person(String firstName, String lastName, String age) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.age = age;
+ }
+
+ @Init
+ private void initNames() {
+ this.firstName = this.firstName.substring(0, 1)
+ .toUpperCase() + this.firstName.substring(1);
+ this.lastName = this.lastName.substring(0, 1)
+ .toUpperCase() + this.lastName.substring(1);
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getAge() {
+ return age;
+ }
+
+ public void setAge(String age) {
+ this.age = age;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+}
diff --git a/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java b/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java
new file mode 100644
index 0000000000..0b1dd952dc
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java
@@ -0,0 +1,62 @@
+package com.baeldung.streamreduce.application;
+
+import com.baeldung.streamreduce.entities.User;
+import com.baeldung.streamreduce.utilities.NumberUtils;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Application {
+
+ public static void main(String[] args) {
+ List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
+ int result1 = numbers.stream().reduce(0, (a, b) -> a + b);
+ System.out.println(result1);
+
+ int result2 = numbers.stream().reduce(0, Integer::sum);
+ System.out.println(result2);
+
+ List letters = Arrays.asList("a", "b", "c", "d", "e");
+ String result3 = letters.stream().reduce("", (a, b) -> a + b);
+ System.out.println(result3);
+
+ String result4 = letters.stream().reduce("", String::concat);
+ System.out.println(result4);
+
+ String result5 = letters.stream().reduce("", (a, b) -> a.toUpperCase() + b.toUpperCase());
+ System.out.println(result5);
+
+ List users = Arrays.asList(new User("John", 30), new User("Julie", 35));
+ int result6 = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
+ System.out.println(result6);
+
+ String result7 = letters.parallelStream().reduce("", String::concat);
+ System.out.println(result7);
+
+ int result8 = users.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
+ System.out.println(result8);
+
+ List userList = new ArrayList<>();
+ for (int i = 0; i <= 1000000; i++) {
+ userList.add(new User("John" + i, i));
+ }
+
+ long t1 = System.currentTimeMillis();
+ int result9 = userList.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
+ long t2 = System.currentTimeMillis();
+ System.out.println(result9);
+ System.out.println("Sequential stream time: " + (t2 - t1) + "ms");
+
+ long t3 = System.currentTimeMillis();
+ int result10 = userList.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
+ long t4 = System.currentTimeMillis();
+ System.out.println(result10);
+ System.out.println("Parallel stream time: " + (t4 - t3) + "ms");
+
+ int result11 = NumberUtils.divideListElements(numbers, 1);
+ System.out.println(result11);
+
+ int result12 = NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 0);
+ System.out.println(result12);
+ }
+}
diff --git a/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java b/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java
new file mode 100644
index 0000000000..bc13a8cde6
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java
@@ -0,0 +1,25 @@
+package com.baeldung.streamreduce.entities;
+
+public class User {
+
+ private final String name;
+ private final int age;
+
+ public User(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ @Override
+ public String toString() {
+ return "User{" + "name=" + name + ", age=" + age + '}';
+ }
+}
diff --git a/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java b/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java
new file mode 100644
index 0000000000..7a6a85e6c4
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java
@@ -0,0 +1,52 @@
+package com.baeldung.streamreduce.utilities;
+
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public abstract class NumberUtils {
+
+ private static final Logger LOGGER = Logger.getLogger(NumberUtils.class.getName());
+
+ public static int divideListElements(List values, Integer divider) {
+ return values.stream()
+ .reduce(0, (a, b) -> {
+ try {
+ return a / divider + b / divider;
+ } catch (ArithmeticException e) {
+ LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero");
+ }
+ return 0;
+ });
+ }
+
+ public static int divideListElementsWithExtractedTryCatchBlock(List values, int divider) {
+ return values.stream().reduce(0, (a, b) -> divide(a, divider) + divide(b, divider));
+ }
+
+ public static int divideListElementsWithApplyFunctionMethod(List values, int divider) {
+ BiFunction division = (a, b) -> a / b;
+ return values.stream().reduce(0, (a, b) -> applyFunction(division, a, divider) + applyFunction(division, b, divider));
+ }
+
+ private static int divide(int value, int factor) {
+ int result = 0;
+ try {
+ result = value / factor;
+ } catch (ArithmeticException e) {
+ LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero");
+ }
+ return result;
+ }
+
+ private static int applyFunction(BiFunction function, int a, int b) {
+ try {
+ return function.apply(a, b);
+ }
+ catch(Exception e) {
+ LOGGER.log(Level.INFO, "Exception occurred!");
+ }
+ return 0;
+ }
+}
diff --git a/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java b/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java
index bad1c32e4a..e742635758 100644
--- a/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java
+++ b/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java
@@ -39,6 +39,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class Java8CollectorsUnitTest {
private final List givenList = Arrays.asList("a", "bb", "ccc", "dd");
+ private final List listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb");
@Test
public void whenCollectingToList_shouldCollectToList() throws Exception {
@@ -48,12 +49,19 @@ public class Java8CollectorsUnitTest {
}
@Test
- public void whenCollectingToList_shouldCollectToSet() throws Exception {
+ public void whenCollectingToSet_shouldCollectToSet() throws Exception {
final Set result = givenList.stream().collect(toSet());
assertThat(result).containsAll(givenList);
}
+ @Test
+ public void givenContainsDuplicateElements_whenCollectingToSet_shouldAddDuplicateElementsOnlyOnce() throws Exception {
+ final Set result = listWithDuplicates.stream().collect(toSet());
+
+ assertThat(result).hasSize(4);
+ }
+
@Test
public void whenCollectingToCollection_shouldCollectToCollection() throws Exception {
final List result = givenList.stream().collect(toCollection(LinkedList::new));
@@ -77,10 +85,23 @@ public class Java8CollectorsUnitTest {
}
@Test
- public void whenCollectingToMap_shouldCollectToMapMerging() throws Exception {
- final Map result = givenList.stream().collect(toMap(Function.identity(), String::length, (i1, i2) -> i1));
+ public void whenCollectingToMapwWithDuplicates_shouldCollectToMapMergingTheIdenticalItems() throws Exception {
+ final Map result = listWithDuplicates.stream().collect(
+ toMap(
+ Function.identity(),
+ String::length,
+ (item, identicalItem) -> item
+ )
+ );
- assertThat(result).containsEntry("a", 1).containsEntry("bb", 2).containsEntry("ccc", 3).containsEntry("dd", 2);
+ assertThat(result).containsEntry("a", 1).containsEntry("bb", 2).containsEntry("c", 1).containsEntry("d", 1);
+ }
+
+ @Test
+ public void givenContainsDuplicateElements_whenCollectingToMap_shouldThrowException() throws Exception {
+ assertThatThrownBy(() -> {
+ listWithDuplicates.stream().collect(toMap(Function.identity(), String::length));
+ }).isInstanceOf(IllegalStateException.class);
}
@Test
diff --git a/core-java-8/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java b/core-java-8/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java
new file mode 100644
index 0000000000..f24b37aef7
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.customannotations;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+public class JsonSerializerUnitTest {
+
+ @Test
+ public void givenObjectNotSerializedThenExceptionThrown() throws JsonSerializationException {
+ Object object = new Object();
+ ObjectToJsonConverter serializer = new ObjectToJsonConverter();
+ assertThrows(JsonSerializationException.class, () -> {
+ serializer.convertToJson(object);
+ });
+ }
+
+ @Test
+ public void givenObjectSerializedThenTrueReturned() throws JsonSerializationException {
+ Person person = new Person("soufiane", "cheouati", "34");
+ ObjectToJsonConverter serializer = new ObjectToJsonConverter();
+ String jsonString = serializer.convertToJson(person);
+ assertEquals("{\"personAge\":\"34\",\"firstName\":\"Soufiane\",\"lastName\":\"Cheouati\"}", jsonString);
+ }
+}
diff --git a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
similarity index 89%
rename from core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java
rename to core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
index ede0ef9f70..835815aecd 100644
--- a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java
+++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
@@ -5,22 +5,21 @@ import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
+import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
-public class MethodReferenceExamples {
+public class MethodReferenceUnitTest {
private static void doNothingAtAll(Object... o) {
}
;
-
+
@Test
public void referenceToStaticMethod() {
List messages = Arrays.asList("Hello", "Baeldung", "readers!");
- messages.forEach((word) -> {
- System.out.println(word);
- });
- messages.forEach(System.out::println);
+ messages.forEach(word -> StringUtils.capitalize(word));
+ messages.forEach(StringUtils::capitalize);
}
@Test
@@ -63,7 +62,7 @@ public class MethodReferenceExamples {
@Test
public void limitationsAndAdditionalExamples() {
createBicyclesList().forEach(b -> System.out.printf("Bike brand is '%s' and frame size is '%d'%n", b.getBrand(), b.getFrameSize()));
- createBicyclesList().forEach((o) -> MethodReferenceExamples.doNothingAtAll(o));
+ createBicyclesList().forEach((o) -> MethodReferenceUnitTest.doNothingAtAll(o));
}
private List createBicyclesList() {
diff --git a/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java b/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java
new file mode 100644
index 0000000000..9222cbb689
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java
@@ -0,0 +1,126 @@
+package com.baeldung.streamreduce.tests;
+
+import com.baeldung.streamreduce.entities.User;
+import com.baeldung.streamreduce.utilities.NumberUtils;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class StreamReduceManualTest {
+
+ @Test
+ public void givenIntegerList_whenReduceWithSumAccumulatorLambda_thenCorrect() {
+ List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
+
+ int result = numbers.stream().reduce(0, (a, b) -> a + b);
+
+ assertThat(result).isEqualTo(21);
+ }
+
+ @Test
+ public void givenIntegerList_whenReduceWithSumAccumulatorMethodReference_thenCorrect() {
+ List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
+
+ int result = numbers.stream().reduce(0, Integer::sum);
+
+ assertThat(result).isEqualTo(21);
+ }
+
+ @Test
+ public void givenStringList_whenReduceWithConcatenatorAccumulatorLambda_thenCorrect() {
+ List letters = Arrays.asList("a", "b", "c", "d", "e");
+
+ String result = letters.stream().reduce("", (a, b) -> a + b);
+
+ assertThat(result).isEqualTo("abcde");
+ }
+
+ @Test
+ public void givenStringList_whenReduceWithConcatenatorAccumulatorMethodReference_thenCorrect() {
+ List letters = Arrays.asList("a", "b", "c", "d", "e");
+
+ String result = letters.stream().reduce("", String::concat);
+
+ assertThat(result).isEqualTo("abcde");
+ }
+
+ @Test
+ public void givenStringList_whenReduceWithUppercaseConcatenatorAccumulator_thenCorrect() {
+ List letters = Arrays.asList("a", "b", "c", "d", "e");
+
+ String result = letters.stream().reduce("", (a, b) -> a.toUpperCase() + b.toUpperCase());
+
+ assertThat(result).isEqualTo("ABCDE");
+ }
+
+ @Test
+ public void givenUserList_whenReduceWithAgeAccumulatorAndSumCombiner_thenCorrect() {
+ List users = Arrays.asList(new User("John", 30), new User("Julie", 35));
+
+ int result = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
+
+ assertThat(result).isEqualTo(65);
+ }
+
+ @Test
+ public void givenStringList_whenReduceWithParallelStream_thenCorrect() {
+ List letters = Arrays.asList("a", "b", "c", "d", "e");
+
+ String result = letters.parallelStream().reduce("", String::concat);
+
+ assertThat(result).isEqualTo("abcde");
+ }
+
+ @Test
+ public void givenNumberUtilsClass_whenCalledDivideListElements_thenCorrect() {
+ List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
+
+ assertThat(NumberUtils.divideListElements(numbers, 1)).isEqualTo(21);
+ }
+
+ @Test
+ public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlock_thenCorrect() {
+ List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
+
+ assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 1)).isEqualTo(21);
+ }
+
+ @Test
+ public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlockAndListContainsZero_thenCorrect() {
+ List numbers = Arrays.asList(0, 1, 2, 3, 4, 5, 6);
+
+ assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 1)).isEqualTo(21);
+ }
+
+ @Test
+ public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlockAndDividerIsZero_thenCorrect() {
+ List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
+
+ assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 0)).isEqualTo(0);
+ }
+
+ @Test
+ public void givenStream_whneCalleddivideListElementsWithApplyFunctionMethod_thenCorrect() {
+ List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
+
+ assertThat(NumberUtils.divideListElementsWithApplyFunctionMethod(numbers, 1)).isEqualTo(21);
+ }
+
+ @Test
+ public void givenTwoStreams_whenCalledReduceOnParallelizedStream_thenFasterExecutionTime() {
+ List userList = new ArrayList<>();
+ for (int i = 0; i <= 1000000; i++) {
+ userList.add(new User("John" + i, i));
+ }
+ long currentTime1 = System.currentTimeMillis();
+ userList.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
+ long sequentialExecutionTime = System.currentTimeMillis() -currentTime1;
+ long currentTime2 = System.currentTimeMillis();
+ userList.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
+ long parallelizedExecutionTime = System.currentTimeMillis() - currentTime2;
+
+ assertThat(parallelizedExecutionTime).isLessThan(sequentialExecutionTime);
+ }
+}
diff --git a/core-java-9/README.md b/core-java-9/README.md
index c96267dc95..224306db19 100644
--- a/core-java-9/README.md
+++ b/core-java-9/README.md
@@ -16,7 +16,7 @@
- [Java 9 Reactive Streams](http://www.baeldung.com/java-9-reactive-streams)
- [Java 9 java.util.Objects Additions](http://www.baeldung.com/java-9-objects-new)
- [Java 9 Variable Handles Demistyfied](http://www.baeldung.com/java-variable-handles)
-- [Exploring the New HTTP Client in Java 9](http://www.baeldung.com/java-9-http-client)
+- [Exploring the New HTTP Client in Java 9 and 11](http://www.baeldung.com/java-9-http-client)
- [Method Handles in Java](http://www.baeldung.com/java-method-handles)
- [Introduction to Chronicle Queue](http://www.baeldung.com/java-chronicle-queue)
- [A Guide to Java 9 Modularity](http://www.baeldung.com/java-9-modularity)
@@ -26,3 +26,6 @@
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
- [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api)
- [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api)
+- [Immutable Set in Java](https://www.baeldung.com/java-immutable-set)
+- [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar)
+- [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation)
diff --git a/core-java-9/compile-aot.sh b/core-java-9/compile-aot.sh
new file mode 100755
index 0000000000..c3a39b0196
--- /dev/null
+++ b/core-java-9/compile-aot.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+cd src/main/java
+javac com/baeldung/java9/aot/JaotCompilation.java
+jaotc --output jaotCompilation.so com/baeldung/java9/aot/JaotCompilation.class
+
diff --git a/core-java-9/run-aot.sh b/core-java-9/run-aot.sh
new file mode 100755
index 0000000000..89fc616469
--- /dev/null
+++ b/core-java-9/run-aot.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+cd src/main/java
+java -XX:AOTLibrary=./jaotCompilation.so com/baeldung/java9/aot/JaotCompilation
\ No newline at end of file
diff --git a/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java b/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java
new file mode 100644
index 0000000000..4d8a018d6b
--- /dev/null
+++ b/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java
@@ -0,0 +1,12 @@
+package com.baeldung.java9.aot;
+
+public class JaotCompilation {
+
+ public static void main(String[] argv) {
+ System.out.println(message());
+ }
+
+ public static String message() {
+ return "The JAOT compiler says 'Hello'";
+ }
+}
\ No newline at end of file
diff --git a/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java b/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java
new file mode 100644
index 0000000000..21bbcc01d4
--- /dev/null
+++ b/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java
@@ -0,0 +1,16 @@
+package com.baeldung.multireleaseapp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class App {
+
+ private static final Logger logger = LoggerFactory.getLogger(App.class);
+
+ public static void main(String[] args) throws Exception {
+ String dateToCheck = args[0];
+ boolean isLeapYear = DateHelper.checkIfLeapYear(dateToCheck);
+ logger.info("Date given " + dateToCheck + " is leap year: " + isLeapYear);
+ }
+
+}
diff --git a/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java b/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java
new file mode 100644
index 0000000000..4d943db30b
--- /dev/null
+++ b/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java
@@ -0,0 +1,22 @@
+package com.baeldung.multireleaseapp;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DateHelper {
+
+ private static final Logger logger = LoggerFactory.getLogger(DateHelper.class);
+
+ public static boolean checkIfLeapYear(String dateStr) throws Exception {
+ logger.info("Checking for leap year using Java 1 calendar API");
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(dateStr));
+ int year = cal.get(Calendar.YEAR);
+ return (new GregorianCalendar()).isLeapYear(year);
+ }
+
+}
diff --git a/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java b/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java
new file mode 100644
index 0000000000..35fb0ada1e
--- /dev/null
+++ b/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java
@@ -0,0 +1,18 @@
+package com.baeldung.multireleaseapp;
+
+import java.time.LocalDate;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DateHelper {
+
+ private static final Logger logger = LoggerFactory.getLogger(DateHelper.class);
+
+ public static boolean checkIfLeapYear(String dateStr) throws Exception {
+ logger.info("Checking for leap year using Java 9 Date Api");
+ return LocalDate.parse(dateStr)
+ .isLeapYear();
+ }
+
+}
diff --git a/core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java b/core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java
new file mode 100644
index 0000000000..0458383e99
--- /dev/null
+++ b/core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java
@@ -0,0 +1,182 @@
+package com.baeldung.processbuilder;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.hasItems;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.ProcessBuilder.Redirect;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class ProcessBuilderUnitTest {
+
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ @Test
+ public void givenProcessBuilder_whenInvokeStart_thenSuccess() throws IOException, InterruptedException, ExecutionException {
+ ProcessBuilder processBuilder = new ProcessBuilder("java", "-version");
+ processBuilder.redirectErrorStream(true);
+
+ Process process = processBuilder.start();
+
+ List results = readOutput(process.getInputStream());
+ assertThat("Results should not be empty", results, is(not(empty())));
+ assertThat("Results should contain java version: ", results, hasItem(containsString("java version")));
+
+ int exitCode = process.waitFor();
+ assertEquals("No errors should be detected", 0, exitCode);
+ }
+
+ @Test
+ public void givenProcessBuilder_whenModifyEnvironment_thenSuccess() throws IOException, InterruptedException {
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ Map environment = processBuilder.environment();
+ environment.forEach((key, value) -> System.out.println(key + value));
+
+ environment.put("GREETING", "Hola Mundo");
+
+ List command = getGreetingCommand();
+ processBuilder.command(command);
+ Process process = processBuilder.start();
+
+ List results = readOutput(process.getInputStream());
+ assertThat("Results should not be empty", results, is(not(empty())));
+ assertThat("Results should contain a greeting ", results, hasItem(containsString("Hola Mundo")));
+
+ int exitCode = process.waitFor();
+ assertEquals("No errors should be detected", 0, exitCode);
+ }
+
+ @Test
+ public void givenProcessBuilder_whenModifyWorkingDir_thenSuccess() throws IOException, InterruptedException {
+ List command = getDirectoryListingCommand();
+ ProcessBuilder processBuilder = new ProcessBuilder(command);
+
+ processBuilder.directory(new File("src"));
+ Process process = processBuilder.start();
+
+ List results = readOutput(process.getInputStream());
+ assertThat("Results should not be empty", results, is(not(empty())));
+ assertThat("Results should contain directory listing: ", results, hasItems(containsString("main"), containsString("test")));
+
+ int exitCode = process.waitFor();
+ assertEquals("No errors should be detected", 0, exitCode);
+ }
+
+ @Test
+ public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessWriting() throws IOException, InterruptedException {
+ ProcessBuilder processBuilder = new ProcessBuilder("java", "-version");
+
+ processBuilder.redirectErrorStream(true);
+ File log = tempFolder.newFile("java-version.log");
+ processBuilder.redirectOutput(log);
+
+ Process process = processBuilder.start();
+
+ assertEquals("If redirected, should be -1 ", -1, process.getInputStream()
+ .read());
+ int exitCode = process.waitFor();
+ assertEquals("No errors should be detected", 0, exitCode);
+
+ List lines = Files.lines(log.toPath())
+ .collect(Collectors.toList());
+
+ assertThat("Results should not be empty", lines, is(not(empty())));
+ assertThat("Results should contain java version: ", lines, hasItem(containsString("java version")));
+ }
+
+ @Test
+ public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessAppending() throws IOException, InterruptedException {
+ ProcessBuilder processBuilder = new ProcessBuilder("java", "-version");
+
+ File log = tempFolder.newFile("java-version-append.log");
+ processBuilder.redirectErrorStream(true);
+ processBuilder.redirectOutput(Redirect.appendTo(log));
+
+ Process process = processBuilder.start();
+
+ assertEquals("If redirected output, should be -1 ", -1, process.getInputStream()
+ .read());
+
+ int exitCode = process.waitFor();
+ assertEquals("No errors should be detected", 0, exitCode);
+
+ List lines = Files.lines(log.toPath())
+ .collect(Collectors.toList());
+
+ assertThat("Results should not be empty", lines, is(not(empty())));
+ assertThat("Results should contain java version: ", lines, hasItem(containsString("java version")));
+ }
+
+ @Test
+ public void givenProcessBuilder_whenStartingPipeline_thenSuccess() throws IOException, InterruptedException {
+ if (!isWindows()) {
+ List builders = Arrays.asList(
+ new ProcessBuilder("find", "src", "-name", "*.java", "-type", "f"),
+ new ProcessBuilder("wc", "-l"));
+
+ List processes = ProcessBuilder.startPipeline(builders);
+ Process last = processes.get(processes.size() - 1);
+
+ List output = readOutput(last.getInputStream());
+ assertThat("Results should not be empty", output, is(not(empty())));
+ }
+ }
+
+ @Test
+ public void givenProcessBuilder_whenInheritIO_thenSuccess() throws IOException, InterruptedException {
+ List command = getEchoCommand();
+ ProcessBuilder processBuilder = new ProcessBuilder(command);
+
+ processBuilder.inheritIO();
+ Process process = processBuilder.start();
+
+ int exitCode = process.waitFor();
+ assertEquals("No errors should be detected", 0, exitCode);
+ }
+
+ private List readOutput(InputStream inputStream) throws IOException {
+ try (BufferedReader output = new BufferedReader(new InputStreamReader(inputStream))) {
+ return output.lines()
+ .collect(Collectors.toList());
+ }
+ }
+
+ private List getDirectoryListingCommand() {
+ return isWindows() ? Arrays.asList("cmd.exe", "/c", "dir") : Arrays.asList("/bin/sh", "-c", "ls");
+ }
+
+ private List getGreetingCommand() {
+ return isWindows() ? Arrays.asList("cmd.exe", "/c", "echo %GREETING%") : Arrays.asList("/bin/bash", "-c", "echo $GREETING");
+ }
+
+ private List getEchoCommand() {
+ return isWindows() ? Arrays.asList("cmd.exe", "/c", "echo hello") : Arrays.asList("/bin/sh", "-c", "echo hello");
+ }
+
+ private boolean isWindows() {
+ return System.getProperty("os.name")
+ .toLowerCase()
+ .startsWith("windows");
+ }
+
+}
diff --git a/core-java-arrays/README.md b/core-java-arrays/README.md
index 400dd7793c..ed8221ebe4 100644
--- a/core-java-arrays/README.md
+++ b/core-java-arrays/README.md
@@ -14,3 +14,4 @@
- [Array Operations in Java](http://www.baeldung.com/java-common-array-operations)
- [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection)
- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays)
+- [Convert a Float to a Byte Array in Java](https://www.baeldung.com/java-convert-float-to-byte-array)
diff --git a/core-java-arrays/pom.xml b/core-java-arrays/pom.xml
index d2d0453e87..ac9f7d08f0 100644
--- a/core-java-arrays/pom.xml
+++ b/core-java-arrays/pom.xml
@@ -4,8 +4,8 @@
com.baeldung
core-java-arrays
0.1.0-SNAPSHOT
- jar
core-java-arrays
+ jar
com.baeldung
@@ -390,7 +390,6 @@
3.8.1
- 1.16.12
1.19
1.19
diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md
index d1112047ba..c5139074e9 100644
--- a/core-java-collections-list/README.md
+++ b/core-java-collections-list/README.md
@@ -5,7 +5,7 @@
### Relevant Articles:
- [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list)
- [Guide to the Java ArrayList](http://www.baeldung.com/java-arraylist)
-- [Random List Element](http://www.baeldung.com/java-random-list-element)
+- [Java – Get Random Item/Element From a List](http://www.baeldung.com/java-random-list-element)
- [Removing all nulls from a List in Java](http://www.baeldung.com/java-remove-nulls-from-list)
- [Removing all duplicates from a List in Java](http://www.baeldung.com/java-remove-duplicates-from-list)
- [How to TDD a List Implementation in Java](http://www.baeldung.com/java-test-driven-list)
@@ -27,3 +27,6 @@
- [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections)
- [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection)
- [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist)
+- [Determine If All Elements Are the Same in a Java List](https://www.baeldung.com/java-list-all-equal)
+- [List of Primitive Integer Values in Java](https://www.baeldung.com/java-list-primitive-int)
+- [Performance Comparison of Primitive Lists in Java](https://www.baeldung.com/java-list-primitive-performance)
diff --git a/core-java-collections-list/pom.xml b/core-java-collections-list/pom.xml
index a7e711088a..217278bdf6 100644
--- a/core-java-collections-list/pom.xml
+++ b/core-java-collections-list/pom.xml
@@ -3,8 +3,8 @@
4.0.0
core-java-collections-list
0.1.0-SNAPSHOT
- jar
core-java-collections-list
+ jar
com.baeldung
@@ -40,17 +40,28 @@
net.sf.trove4j
trove4j
- 3.0.2
+ ${trove4j.version}
it.unimi.dsi
fastutil
- 8.1.0
+ ${fastutil.version}
colt
colt
- 1.2.0
+ ${colt.version}
+
+
+
+ org.openjdk.jmh
+ jmh-core
+ ${jmh-core.version}
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${jmh-core.version}
@@ -59,6 +70,8 @@
3.8.1
1.7.0
3.11.1
- 1.16.12
+ 3.0.2
+ 8.1.0
+ 1.2.0