Untitled

 avatar
unknown
plain_text
a year ago
65 kB
3
Indexable
algorithmandstructure.datastructure 

1. limitedaccess
	1.1. Queue

1. Queue
A queue is an abstract data type where elements are inserted and removed according to the first-in-first-out (FIFO)
principle.

2. Structure
The elements in the queue stand consecutively, with FRONT pointing at the first element and REAR pointing at the last
element.

3. Queue operations
The operation when you insert an element into the queue is called enqueue, and the element is added by the REAR pointer.
If you remove an element, this operation is called dequeue, and the element that was pointed at by FRONT comes out of
the queue.

4. Implementation of queue
    4.1. Array
    In such an implementation, FRONT and REAR can simply be numeric variables that store the indices of the
    corresponding elements. Then you can access both the first element and the last one in a constant time: the enqueue
    and dequeue operations will take O(1).
    However, there is a problem with this implementation: adding and removing elements, you move through the array,
    which means you need an array of an infinite length.

    4.2. Linked list
    The queue can also be implemented in a linked list, in which each element stores a link to the next one. FRONT and
    REAR are then pointers to the first and last nodes in the list, which again allows you to do insertion and deletion
    of elements in O(1). But storing a link to the next item in each item means wasting a lot more memory than the data
    requires.

###########################################

	1.2. Stack

1. Stack essentials
A stack is an abstract data type where elements are inserted and removed according to the last-in-first-out (LIFO)
principle. The push operation inserts an item at the top of the stack, the pop operation removes the top item from the
stack.
Access to arbitrary elements is restricted. As a rule, a stack also supports the peek operation that just returns the
current top element.

2. Stacks in real-life and programming
In programming, stacks are used to:
- evaluate arithmetic expressions;
- store arguments of functions and results of the functions' calls;
- reverse the order of elements.

3. The efficiency of stacks
If you use a linked list or a classic array (non-resizable) as an internal structure, both push and pop operations
always take constant O(1) time. It does not depend on how many elements there are in the stack, so the operations are
very quick.

##############################################

2. linearstructure
	2.1. DynamicArray

1. Essentials
A dynamic array is a linear data structure that is able to grow and, in some implementations, shrink when its size
changes. As a rule, it has an internal regular array that actually stores data under the hood and provides some
additional operations on top of it.

A dynamic array has two important properties:
- size – the number of elements already stored in it;
- capacity – a possible number of elements to be stored that corresponds to the size of the internal regular array.

2. Scaling factor
If the number of elements exceeds the capacity, all elements will be copied to a new internal array of a bigger size.
The most common ones are the multiplication of the initial capacity by 1.5 (Java) or 2 (C++, the GCC STL implementation).
There are also more unique cases like the Golang dynamic array ("slice"), which doubles the size until 1024 elements
(after that the ratio is 5/4).
What value will have both optimal time and space complexities? It turns out, that the value must be equal to the golden
ratio, 1.61803. As you may notice, 1.5 is as close to it as it can get. If you're interested, you can read more about it.
It may also be necessary to support the shrinking of the internal array when removing elements to reduce the required
size.

3. Common operations
Add an element to the end of the array:
- O(1): in average cases, since we just insert an element to already allocated memory (less than capacity)
- O(n): in the worst case, where we ran out of space and need to allocate a new array and copy every element into it.

Add an element at the specified index:
Its complexities (both average and worst) would be O(n) since on each insertion we must move an element at the index we
want and then move each next element one index to the right.

Update value at the specified index:
The complexities are both O(1)

Remove an element by value/index:
The complexities would be O(n)

Clear:
We can just reset the size to zero and override the old elements during the following inserts. That would leave the
elements hanging out in memory (so the garbage collector won't be able to collect them) until they are overridden. The
simplest form would have complexities of O(1), but the right one would be O(n)

Get element by index:
We can access elements by their index in constant time, so complexities are O(1)

####################################################

	2.2. FixedSizeArray

1. Fixed-size array
A fixed-size array is a structure for storing a collection of elements of the same type. The size of such an array is a
constant: once an array is created, you can't change its size. While creating a fixed-size array, we declare its size.
The computer then reserves necessary memory resources for the array. After that, the elements of a fixed-size array are
stored sequentially into those memory addresses.

Using pseudocode, we can represent the first array as follows:
measurements = [10.8, 14.3, 13.5, 12.1, 9.7]

2. Accessing elements
Take notice that we can not only read, but also modify elements of an array:
measurements[2] = 3.7

Both reading and modifying operations require O(1) time complexity. It's so efficient, because by knowing the index
number, the computer can jump directly to the required memory address and fetch or modify the data.

3. Inserting and deleting elements
In short, inserting an element into a fixed-size array or deleting an element from the array is not possible.
If you still want to add new element, you need to create another array to store the entire element in the old array and
the element you want to add.
This operation requires O(n) time complexity, where n is the number of elements of the array. In terms of performance,
inserting and deleting are very slow operations for a fixed-size array. To overcome this limitation, programmers have
introduced dynamic arrays

######################################################

algorithmandstructure.intro

1. basic
	1.1. AbstractionAndConcretion

1. Abstract Data Type (ADT)
- Abstraction — a concept in object-oriented programming; it "shows" only essential attributes and "hides" unnecessary
  information, a.k.a. abstract classes or interfaces;
- Encapsulation — is the process of combining data and code, operating this data into a single entity. The user needn't
  worry about the internal details and complexities of the system.

An Abstract Data Type is a data type that is defined by a set of values (elements/items) and a set of possible external
operations (behavior) from the user's point of view. There are some common ADTs that every trained programmer should
know: stack, queue, and so on.


2. CDT vs ADT
Data structures (CDTs) are exact representations of data, but ADTs are different: they reflect the point of view of a
user, not an implementer. A data structure (CDT) is an implementation of an ADT's functions, a way to look more closely
at some specific operations and components of the structure.

Recall from the previous section, that a stack is an abstract data type. It may define operations like push, pop, and
peek, regardless of whether it is implemented using an array or a linked list. On the other hand, each one of these
possible implementations defines a concrete data structure. java.util.Map, for example, plays the role of an ADT,
whereas HashMap or LinkedHashMap can be interpreted as data structures.

#######################################################

2. representation
	2.1. ComplexConstructions

1. Loops
A while loop looks like this:
i = 0
while i < 5:
    print(i)
    i = i + 1

Here is what the for loop looks like:
sum = 0
for i in (1, 9):
    sum = sum + i
print(sum) // 45, sum of numbers from 1 to 9


2. Arrays
If we need an array and want to initialize its elements later, we will write the following construction:
array[1, 10] // 10-element array with indices from 1 to 10

We can also initialize an array with some data explicitly:
fib = [0, 1, 1, 2, 3, 5, 8] // array with the name fib

Enumeration of elements starts with 1. As you may know, array indices in programming often start with 0, but we will
use a common pseudocode approach.
x = fib[4] // x is 2
length = len(fib) // length is 7
for i in (1, len(fib)):
    print(fib[i])

Another useful operation is getting a subarray of an array. It functions as follows:
array = [0, 3, 2, 4, 1]
subarray = array[2, 4]
print(subarray) // 3, 2, 4


4. Functions
Below is a function that calculates the mean value of numbers in an array:

function calc_mean(array):
    sum = 0

    for i in (1, len(array)):
        sum = sum + array[i]

    return sum / len(array)


5. Implementing simple algorithms in pseudocode
The first example is a function that takes an array of numbers as input and returns either zero (if the array is empty)
or the maximum number in the array:

function find_max(array):
    if len(array) == 0 then:
        return 0

    max = array[1]

    for i in (2, len(array)):
        if array[i] > max then:
            max = array[i]

    return max

Another example is a function that merges two arrays. It takes two sorted arrays as input and returns one sorted array
containing the numbers from both input arrays:

function merge(left, right):
    merged[1, len(left) + len(right)] // new array

    i = 1      //
    j = 1      // indices for loop
    k = 1      //

    // iterate over two arrays while both of them have elements left
    while i <= len(left) and j <= len(right):
        if left[i] < right[j] then:    // put element from left array to merged array
            merged[k] = left[i]
            i = i + 1   // move to next element in left array
        else:
            merged[k] = right[j] // put element from right array to merged array
            j = j + 1   // move to next element in right array
        k = k + 1   // move to next element in merged array

    while i <= len(left):    // move remaining element in left array to merged array
        merged[k] = left[i]
        i = i + 1
        k = k + 1

    while j <= len(right):   // move remaining element in right array to merged array
        merged[k] = right[j]
        j = j + 1
        k = k + 1

    return merged

NOTE
we don't care about passing arguments by value, by reference, and so on. If you change any variable inside the function,
those changes are saved outside the function. Thus, if you need to keep an argument immutable, just make a copy of it to
operate with. Consider this example of the swap function that swaps two variables:

function swap(a, b):
    temp = a
    a = b
    b = temp

c = 3
d = 5

swap(c, d)

print(c) // 5
print(d) // 3

########################################

	2.2. Pseudocode

Pseudocode example

Let's solve a standard task and find the maximum value in an array of positive numbers:

function max(array):            // you receive an array somehow
    if len(array) == 0 then:     // compare the size of array with 0
        return -1               // empty array, no maximum

    max = 0                     // assume that the maximum is 0

    for i in [1, len(array)]:    // iterate over the array,
                                 // array indices start at 1
        if array[i] > max then:  // if we find something greater,
            max = array[i]      //  we change the maximum

    return max                 // our result

#######################################

	2.3. PseudocodeBasic

1. Variables and assigning
The syntax is pretty simple: the name of the variable is on the left, the value is on the right, the assignment operator
is in between:
a = 93
b = 3.14
c = "Hello"

or a shorter version:
a, b, c = 3, "text", 5.5


2. Input and output data
a = input() // a is a number
b = input() // b is a string

s = "Hello"
print(s)


3. Comments
// this is a comment
a = 10  // assigning 10 to the variable a
b = 42  // another assignment


4. Arithmetic operations
a = 7
b = 2

sum = a + b        // addition, sum is equal to 9
dif = a - b        // subtraction, dif is equal to 5

prod = a * b       // multiplication, prod is equal to 14
quot = a / b       // division, quot is equal to 3.5
rem = a mod b      // modulo division, rem is equal to 1
quot_int = a div b // integer division, quot_int is equal to 3

a = 3
b = 5

a = a + b
a = a - b


5. Relational and logical operators
Relational operators:
a == b // a equal to b
a != b // a is not equal to b
a < b  // a is less than b
a <= b // a is less than or equal to b
a > b  // a is greater than b
a >= b // a is greater than or equal to b

Logical operators:
true and true == true
true and false == false
false and true == false
false and false == false

true or true == true
true or false == true
false or true == true
false or false == false

not true == false
not false == true


6. Conditional statements
Let's have a look at an example:
a = 3

if a < 5 then:
    print(a)

a = 10
b = 20

if (a == 10 and b == 20) or not (a == 20 and b == 10) then:
    print(a)
    print(b)

a = -3

if a > 0 then:
    print("positive")
else:
    print("negative or zero") // prints this

a = -5

if a > 0 then:            // false
    print("positive")
elif a == 0 then:         // checks this
    print("zero")
else:
    print("negative")     // output

#################################################

javacore.addition.essentialstandardclass

1. computation
	1.1. MyBigDecimal

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Scanner;

public class MyBigDecimal {

    public static void main(String[] args) {
        BigDecimalExercise.roundAndPower();
    }

    public static void creatingObjectOfBigDecimal() {
        BigDecimal firstBigDecimal = new BigDecimal("10000000000000.5897654329");

        BigDecimal zero = BigDecimal.ZERO; // 0
        BigDecimal one = BigDecimal.ONE;   // 1
        BigDecimal ten = BigDecimal.TEN;   // 10
    }

    public static void arithmeticOperators() {
        BigDecimal first = new BigDecimal("0.2");
        BigDecimal second = new BigDecimal("0.1");

        BigDecimal addition = first.add(second);            // 0.3
        BigDecimal subtraction = first.subtract(second);    // 0.1
        BigDecimal multiplication = first.multiply(second); // 0.02
        BigDecimal division = first.divide(second);         // 2
        BigDecimal remainder = first.remainder(second);     // 0.0

        BigDecimal module = first.abs();  //  0.2
        BigDecimal power = first.pow(3); // 0.008
    }

    public static void roundingControl() {
        BigDecimal bigDecimal = new BigDecimal("100.5649");
        System.out.println(bigDecimal.setScale(3, RoundingMode.CEILING));     // 100.565

        bigDecimal = new BigDecimal("0.55");
        System.out.println(bigDecimal.setScale(1, RoundingMode.HALF_DOWN));   // 0.5
        System.out.println(bigDecimal.setScale(3, RoundingMode.UNNECESSARY)); // 0.550

        // Remember that BigDecimal numbers are immutable, so it is not enough to simply apply setScale() in order for
        // your number to retain the new value after rounding. You need to assign:
        bigDecimal = new BigDecimal("999999999999999999.99999999999999");
        bigDecimal.setScale(3, RoundingMode.HALF_UP);
        System.out.println(bigDecimal); // 999999999999999999.99999999999999

        bigDecimal = bigDecimal.setScale(3, RoundingMode.HALF_UP);
        System.out.println(bigDecimal); // 1000000000000000000.000
    }

    public static void roundingInArithmeticOperators() {
        // If the result of a division has a non-terminating decimal expansion, it cannot be represented as a BigDecimal
        // and ArithmeticException happens:
        BigDecimal dividend = new BigDecimal("1");
        BigDecimal divisor = new BigDecimal("3");

        // java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result
        // BigDecimal quotient = dividend.divide(divisor);

        BigDecimal quotient = dividend.divide(divisor, 2, RoundingMode.HALF_EVEN); // 0.33

        // An exact scale is used if the result can be represented by a finite decimal expansion:
        BigDecimal first = new BigDecimal("20.002");
        BigDecimal second = new BigDecimal("10");
        BigDecimal division = first.divide(second);   // 2.0002

        // Addition, subtraction, and multiplication have no such peculiarities. Even though precision also matters
        // there and is used in arithmetic operations, it's quite intuitive:
        first = new BigDecimal("7.7777");
        second = new BigDecimal("3.3");
        BigDecimal addition = first.add(second);   // 11.0777; The result scale is 4 (max of the scales)
        BigDecimal subtraction = first.subtract(second);   // 4.4777; The result scale is 4 (max of the scales)
        BigDecimal multiplication = first.multiply(second); // 25.66641; The result scale is 5 (sum of the scales)

    }
}

class BigDecimalExercise {

    public static void goldMining() {
        Scanner scanner = new Scanner(System.in);
        var dwalin = scanner.nextBigDecimal();
        var balin = scanner.nextBigDecimal();
        var thorin = scanner.nextBigDecimal();

        var totalGold = dwalin.add(balin).add(thorin);
        System.out.println(totalGold);
    }

    public static void roundAndPower() {
        Scanner scanner = new Scanner(System.in);
        var power = scanner.nextInt();
        var scale = scanner.nextInt();
        var number = scanner.nextBigDecimal();

        var result = number.setScale(scale, RoundingMode.FLOOR).pow(power);
        System.out.println(result);
    }
}

#########################
	1.2. MyBigInteger

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Scanner;

public class MyBigDecimal {

    public static void main(String[] args) {
        BigDecimalExercise.roundAndPower();
    }

    public static void creatingObjectOfBigDecimal() {
        BigDecimal firstBigDecimal = new BigDecimal("10000000000000.5897654329");

        BigDecimal zero = BigDecimal.ZERO; // 0
        BigDecimal one = BigDecimal.ONE;   // 1
        BigDecimal ten = BigDecimal.TEN;   // 10
    }

    public static void arithmeticOperators() {
        BigDecimal first = new BigDecimal("0.2");
        BigDecimal second = new BigDecimal("0.1");

        BigDecimal addition = first.add(second);            // 0.3
        BigDecimal subtraction = first.subtract(second);    // 0.1
        BigDecimal multiplication = first.multiply(second); // 0.02
        BigDecimal division = first.divide(second);         // 2
        BigDecimal remainder = first.remainder(second);     // 0.0

        BigDecimal module = first.abs();  //  0.2
        BigDecimal power = first.pow(3); // 0.008
    }

    public static void roundingControl() {
        BigDecimal bigDecimal = new BigDecimal("100.5649");
        System.out.println(bigDecimal.setScale(3, RoundingMode.CEILING));     // 100.565

        bigDecimal = new BigDecimal("0.55");
        System.out.println(bigDecimal.setScale(1, RoundingMode.HALF_DOWN));   // 0.5
        System.out.println(bigDecimal.setScale(3, RoundingMode.UNNECESSARY)); // 0.550

        // Remember that BigDecimal numbers are immutable, so it is not enough to simply apply setScale() in order for
        // your number to retain the new value after rounding. You need to assign:
        bigDecimal = new BigDecimal("999999999999999999.99999999999999");
        bigDecimal.setScale(3, RoundingMode.HALF_UP);
        System.out.println(bigDecimal); // 999999999999999999.99999999999999

        bigDecimal = bigDecimal.setScale(3, RoundingMode.HALF_UP);
        System.out.println(bigDecimal); // 1000000000000000000.000
    }

    public static void roundingInArithmeticOperators() {
        // If the result of a division has a non-terminating decimal expansion, it cannot be represented as a BigDecimal
        // and ArithmeticException happens:
        BigDecimal dividend = new BigDecimal("1");
        BigDecimal divisor = new BigDecimal("3");

        // java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result
        // BigDecimal quotient = dividend.divide(divisor);

        BigDecimal quotient = dividend.divide(divisor, 2, RoundingMode.HALF_EVEN); // 0.33

        // An exact scale is used if the result can be represented by a finite decimal expansion:
        BigDecimal first = new BigDecimal("20.002");
        BigDecimal second = new BigDecimal("10");
        BigDecimal division = first.divide(second);   // 2.0002

        // Addition, subtraction, and multiplication have no such peculiarities. Even though precision also matters
        // there and is used in arithmetic operations, it's quite intuitive:
        first = new BigDecimal("7.7777");
        second = new BigDecimal("3.3");
        BigDecimal addition = first.add(second);   // 11.0777; The result scale is 4 (max of the scales)
        BigDecimal subtraction = first.subtract(second);   // 4.4777; The result scale is 4 (max of the scales)
        BigDecimal multiplication = first.multiply(second); // 25.66641; The result scale is 5 (sum of the scales)

    }
}

class BigDecimalExercise {

    public static void goldMining() {
        Scanner scanner = new Scanner(System.in);
        var dwalin = scanner.nextBigDecimal();
        var balin = scanner.nextBigDecimal();
        var thorin = scanner.nextBigDecimal();

        var totalGold = dwalin.add(balin).add(thorin);
        System.out.println(totalGold);
    }

    public static void roundAndPower() {
        Scanner scanner = new Scanner(System.in);
        var power = scanner.nextInt();
        var scale = scanner.nextInt();
        var number = scanner.nextBigDecimal();

        var result = number.setScale(scale, RoundingMode.FLOOR).pow(power);
        System.out.println(result);
    }
}

##########################################

2. dateandtime
	2.1. ComparingDatesAndTime

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class ComparingDatesAndTime {

    public static void main(String[] args) {
        theMethodCompareTo();
        otherMethods();
    }

    public static void theMethodCompareTo() {
        LocalDate date1 = LocalDate.parse("2017-01-02");
        LocalDate date2 = LocalDate.parse("2017-12-12");

        date1.compareTo(date1); // 0, date1 and date1 are equal
        date1.compareTo(date2); // -11, negative value => date1 is less than date2
        date2.compareTo(date1); // 11, positive value => date2 is greater than date1

        LocalTime time1 = LocalTime.parse("15:30:10");
        LocalTime time2 = LocalTime.parse("17:50");

        time1.compareTo(time1); // 0, time1 and time1 are equal
        time1.compareTo(time2); // -1, time1 is less than time2
        time2.compareTo(time1); // 1, time2 is greater than time1

        LocalDateTime dateTime1 = LocalDateTime.parse("2017-01-01T20:30"); // 1 January 2017, 20:30
        LocalDateTime dateTime2 = LocalDateTime.parse("2017-01-02T23:00"); // 2 January 2017, 23:00

        dateTime1.compareTo(dateTime1); // 0, dateTime1 and dateTime are equal
        dateTime1.compareTo(dateTime2); // -1, dateTime1 is less than dateTime2
        dateTime2.compareTo(dateTime1); // 1, dateTime2 is greater than dateTime1
    }

    public static void otherMethods() {
        // The classes also provide some concise methods to compare dates and time on a timeline that return boolean value.
        LocalDate date1 = LocalDate.of(2017, 11, 30);
        LocalDate date2 = LocalDate.of(2017, 12, 1);

        date1.isEqual(date1); // true
        date1.isEqual(date2); // false

        date1.isBefore(date2); // true
        date1.isBefore(date1); // false
        date2.isBefore(date1); // false

        date2.isAfter(date1); // true
        date2.isAfter(date2); // false
        date1.isAfter(date2); // false

        // The class LocalTime doesn't have the method isEqual. You can use the method equals instead.
        LocalTime time1 = LocalTime.of(14, 20); // 14:20
        LocalTime time2 = LocalTime.of(15, 55); // 15:55
        LocalTime time3 = LocalTime.of(16, 40); // 16:40

        System.out.println(time1.equals(LocalTime.parse("14:20"))); // true

        time1.isBefore(time2); // true
        time3.isBefore(time2); // false
        time3.isBefore(time3); // false

        time2.isAfter(time1);  // true
        time2.isAfter(time3);  // false

        LocalDateTime dateTime1 = LocalDateTime.parse("2017-12-01T21:30"); // 1 December 2017, 21:30
        LocalDateTime dateTime2 = LocalDateTime.parse("2017-12-02T21:30"); // 2 December 2017, 21:30

        dateTime1.isEqual(dateTime2); // false
        dateTime2.isEqual(dateTime2); // true

        dateTime1.isBefore(dateTime2); // true

        dateTime1.isAfter(dateTime2); // false
        dateTime2.isAfter(dateTime1); // true
    }
}

####################################

	2.2. MyInstant

import java.time.*;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;

/**
 * The Instant class: a date-time unit suitable for capturing event timestamps during the application execution.
 * <p>
 * Instant is a representation of a moment on a timeline relative to an epoch. LocalDateTime is a representation of a
 * calendar date and daytime combination. The first one stores its value in seconds and nanoseconds, while the second one
 * stores it as a pair of LocalDate and LocalTime objects.
 */

public class MyInstant {

    public static void main(String[] args) {
        instantVsLocalDateTime();
    }

    public static void creationMethods() {
        // The Instant units are created in a similar way to Period and Duration class units. It provides static methods
        // for creating the date and time in the ISO 8601 format.
        // Instant values are stored in a long variable storing the seconds counting from the Java epoch and an int
        // variable storing the nanoseconds of a second.
        Instant epoch = Instant.EPOCH;
        System.out.println(epoch); // 1970-01-01T00:00:00Z

        // When working with the Instant class, you specify the date before or after the epoch time counting in seconds
        // and nanoseconds.
        long posValue = 1234567890L;
        long negValue = -1234567890L;

        // Adding specified milliseconds to epoch
        Instant milli = Instant.ofEpochMilli(posValue); // 1970-01-15T06:56:07.890Z
        // Adding specified seconds to epoch
        Instant second = Instant.ofEpochSecond(posValue); // 2009-02-13T23:31:30Z
        // Adding specified seconds and nanoseconds to epoch
        Instant secondNano = Instant.ofEpochSecond(posValue, 123L); // 2009-02-13T23:31:30.000000123Z
        // Adding specified seconds and nanoseconds to epoch. Version 2
        Instant nanoRounded = Instant.ofEpochSecond(posValue, 1_000_000_123L); // 2009-02-13T23:31:31.000000123Z

        // Subtracting specified milliseconds from epoch
        milli = Instant.ofEpochMilli(negValue); // 1969-12-17T17:03:52.110Z
        // Subtracting specified seconds from epoch
        second = Instant.ofEpochSecond(negValue); // 1930-11-18T00:28:30Z
        // Subtracting specified seconds and nanoseconds from epoch
        secondNano = Instant.ofEpochSecond(negValue, -150L); // 1930-11-18T00:28:29.999999850Z
        // Subtracting specified seconds and nanoseconds from epoch. Version 2
        nanoRounded = Instant.ofEpochSecond(negValue, -1_000_000_150L); // 1930-11-18T00:28:28.999999850Z

        // There will be many situations where you will need to obtain an Instant unit for a given time zone. In such
        // cases you can use the ZoneId class to specify the zone:
        Instant instant = Instant.ofEpochSecond(1234567890L);

        System.out.println(instant); // 2009-02-13T23:31:30Z
        System.out.println(instant.atZone(ZoneId.of("GMT+4"))); // 2009-02-14T03:31:30+04:00[GMT+04:00]
        System.out.println(instant.atZone(ZoneId.of("+04:00"))); // 2009-02-14T03:31:30+04:00
        System.out.println(instant.atZone(ZoneId.of("Asia/Yerevan"))); // 2009-02-14T03:31:30+04:00[Asia/Yerevan]
        System.out.println(instant.atZone(ZoneId.systemDefault())); // 2009-02-14T06:31:30+07:00[Asia/Bangkok]

        System.out.println(ZoneId.systemDefault().getId()); // Asia/Bangkok
        System.out.println(ZoneId.systemDefault().getRules()); // ZoneRules[currentStandardOffset=+07:00]

        // The next method for creating Instant units is Instant.parse(), which creates a unit object by accepting a
        // text and parsing it to the Instant type.
        instant = Instant.parse("2009-02-14T03:31:30Z");

        System.out.println(instant); // 2009-02-14T03:31:30Z
        System.out.println(instant.atZone(ZoneId.of("GMT+4"))); // 2009-02-14T07:31:30+04:00[GMT+04:00]
    }

    public static void operationMethods() {
        // isBefore() and isAfter()
        Instant instant1 = Instant.ofEpochSecond(123456L);
        Instant instant2 = Instant.ofEpochSecond(123456789L);

        System.out.println(instant1.isAfter(instant2)); // false
        System.out.println(instant1.isBefore(instant2)); // true

        // compareTo()
        System.out.println(instant1.compareTo(instant2)); // -1

        // This class doesn't implement the addTo() and subtractFrom() methods that are implemented in the Period and
        // Duration classes, but it implements some others:
        // minus(), plus() and their "subversions", such as minusSeconds(), plusSeconds(), and so on.
        Instant instant = Instant.ofEpochSecond(123456L);
        System.out.println(instant); // 1970-01-02T10:17:36Z

        System.out.println(instant.minus(Period.ofDays(1))); // 1970-01-01T10:17:36Z
        System.out.println(instant.minus(Duration.ofDays(1))); //  1970-01-01T10:17:36Z
        System.out.println(instant.minus(1, ChronoUnit.DAYS)); // 1970-01-01T10:17:36Z

        System.out.println(instant.plus(Period.ofDays(1))); // 1970-01-03T10:17:36Z
        System.out.println(instant.plus(Duration.ofDays(1))); // 1970-01-03T10:17:36Z
        System.out.println(instant.plus(1, ChronoUnit.DAYS)); // 1970-01-03T10:17:36Z

        // System.out.println(instant.minus(Period.of(123, 12, 3))); // UnsupportedTemporalTypeException
        // System.out.println(instant.plus(1, ChronoUnit.WEEKS)); // UnsupportedTemporalTypeException

        System.out.println(instant.plus(Period.ofWeeks(1))); // 1970-01-09T10:17:36Z

        // This class has one more interesting method to calculate the difference between two units. It shows the time
        // until another Instant unit is in the form of the specified unit:
        instant = Instant.ofEpochSecond(100200300L);
        System.out.println(Instant.EPOCH.until(instant, ChronoUnit.DAYS)); // 1159
        System.out.println(Instant.EPOCH.until(instant, ChronoUnit.HOURS)); // 27833
    }

    public static void getOperations() {
        Instant ofEpochSecond = Instant.ofEpochSecond(123456L, 789L);
        System.out.println(ofEpochSecond); // 1970-01-02T10:17:36.000000789Z
        System.out.println(ofEpochSecond.getEpochSecond()); // 123456

        System.out.println(ofEpochSecond.get(ChronoField.MICRO_OF_SECOND)); // 0
        System.out.println(ofEpochSecond.get(ChronoField.MILLI_OF_SECOND)); // 0
        System.out.println(ofEpochSecond.get(ChronoField.NANO_OF_SECOND)); // 789

        System.out.println(ofEpochSecond.getLong(ChronoField.INSTANT_SECONDS)); // 123456
        System.out.println(ofEpochSecond.getLong(ChronoField.MICRO_OF_SECOND)); // 0
        System.out.println(ofEpochSecond.getLong(ChronoField.MILLI_OF_SECOND)); // 0
        System.out.println(ofEpochSecond.getLong(ChronoField.NANO_OF_SECOND)); // 789
    }

    public static void instantVsLocalDateTime() {
        // LocalDateTime doesn't contain any information regarding a time zone, but if you create its object with the
        // now() method, it will be created depending on your system's default zone. On the other hand, Instant contains
        // that information and shows the GMT0 time-stamp by default in any case.

        Instant instant = Instant.now(); // System time zone independent, shows GMT0
        System.out.println(instant); // 2024-01-29T10:15:56.027551Z

        LocalDateTime dateTime = LocalDateTime.now(); // System time zone dependent
        System.out.println(dateTime); // 2024-01-29T17:15:56.038550800
    }
}

##########################################

	2.3. MyLocalDateTime

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.Scanner;

/**
 * The class LocalDateTime is a combination of LocalDate and LocalTime that keeps such values as 2017-12-03T22:30.
 * LocalDateTime is also an immutable class from the java.time package.
 */

public class MyLocalDateTime {

    public static void creating() {
        LocalDateTime now = LocalDateTime.now(); // this moment

        LocalDateTime dt1 = LocalDateTime.of(2017, 11, 25, 22, 30);  // 25 November 2017, 22:30
        System.out.println(dt1); // 2017-11-25T22:30
        LocalDateTime dt2 = LocalDateTime.parse("2017-11-25T22:30:45"); // 25 November 2017, 22:30
        System.out.println(dt2); // 2017-11-25T22:30:45

        // It's also possible to obtain an instance from the instances of LocalDate and LocalTime, like this:
        LocalDate date = LocalDate.of(2017, 11, 25); // 2017-11-25
        LocalTime time = LocalTime.of(21, 30); // 21:30
        LocalDateTime dateTime = LocalDateTime.of(date, time); // 2017-11-25T21:30

        // or by using special instance methods of LocalDate and LocalTime:
        date = LocalDate.of(2017, 11, 25); // 2017-11-25
        time = LocalTime.of(21, 30); // 21:30
        LocalDateTime dateTime1 = date.atTime(time); // 2017-11-25T21:30
        LocalDateTime dateTime2 = time.atDate(date); // 2017-11-25T21:30
    }

    public static void fromYearsToMinutes() {
        LocalDateTime dateTime = LocalDateTime.of(2017, 11, 25, 22, 30); // 25 November 2017, 22:30

        // The class LocalDateTime has methods for obtaining units of date and time, such as a month, day of the month,
        // hour and minute:
        int month = dateTime.getMonthValue(); // 11
        int day = dateTime.getDayOfMonth(); // 25
        int hour = dateTime.getHour(); // 22
        int minute = dateTime.getMinute(); // 30

        // The class also has instance methods toLocalDate and toLocalTime to get the date and time as the whole parts
        // of LocalDateTime
        LocalDate dateOf = dateTime.toLocalDate(); // 2017-11-25
        LocalTime timeOf = dateTime.toLocalTime(); // 22:30
    }

    public static void arithmeticMethods() {
        LocalDateTime endOf2017 = LocalDateTime.of(2017, 12, 31, 23, 59, 59); // 2017-12-31T23:59:59

        LocalDateTime beginningOf2018 = endOf2017.plusSeconds(1); // 2018-01-01T00:00
        LocalDateTime beginningOf2020 = beginningOf2018.plusYears(2); // 2020-01-01T00:00

        beginningOf2020 = beginningOf2018.withYear(2020); // 2020-01-01T00:00
    }

    public static void main(String[] args) {

    }
}

class LocalDateTimeExercise {

    public static LocalDateTime merge(LocalDateTime dateTime1, LocalDateTime dateTime2) {
        // write your code here
        int year = Math.max(dateTime1.getYear(), dateTime2.getYear());
        int month = Math.max(dateTime1.getMonthValue(), dateTime2.getMonthValue());
        int day = Math.max(dateTime1.getDayOfMonth(), dateTime2.getDayOfMonth());
        int hour = Math.max(dateTime1.getHour(), dateTime2.getHour());
        int minute = Math.max(dateTime1.getMinute(), dateTime2.getMinute());
        int second = Math.max(dateTime1.getSecond(), dateTime2.getSecond());

        return LocalDateTime.of(year, month, day, hour, minute, second);
    }

    public static void theBeginningOfYear() {
        Scanner scanner = new Scanner(System.in);
        var dateTimeString = scanner.next();

        var dateTime = LocalDateTime.parse(dateTimeString);
        var beginningOfYear = LocalDateTime.of(dateTime.getYear(), 1, 1, 0, 0);
        var hours = beginningOfYear.until(dateTime, ChronoUnit.HOURS);

        System.out.println(hours);
    }

    public static void addDaysAndSubtractHours() {
        Scanner scanner = new Scanner(System.in);
        var dateTimeString = scanner.next();
        var days = scanner.nextInt();
        var hours = scanner.nextInt();

        var dateTime = LocalDateTime.parse(dateTimeString);
        System.out.println(dateTime.plusDays(days).minusHours(hours));
    }

    public static void addingNMinutes() {
        Scanner scanner = new Scanner(System.in);
        var dateTimeString = scanner.next();
        var minutes = scanner.nextLong();

        var dateTime = LocalDateTime.parse(dateTimeString);
        var afterDateTime = dateTime.plusMinutes(minutes);

        System.out.println(afterDateTime.getYear() + " "
                + afterDateTime.getDayOfYear() + " "
                + afterDateTime.toLocalTime()
        );
    }

}

##############################################

	2.4. MyLocalTime

import java.time.LocalTime;
import java.util.Scanner;

/**
 * The LocalTime class represents daytime in the hours-minutes-seconds format, such as 06:30 or 11:45:30. It doesn't
 * store information about the date or the time zone. Time is stored with nanosecond precision (for example, 13:45:30.123456789).
 */

public class MyLocalTime {

    public static void main(String[] args) {
        System.out.println(LocalTime.parse("23:50").plusMinutes(20)
        );
    }

    public static void creating() {
        LocalTime now = LocalTime.now();
        System.out.println(now);

        // If we want to pass a specific time to an instance, we should employ either of the two static methods
        // of and parse to create an instance of LocalTime :
        LocalTime.of(11, 45);        // 11:45
        LocalTime.of(11, 45, 30);    // 11:45:30
        LocalTime.parse("11:45:30"); // 11:45:30 (hours, minutes, seconds)

        // The hour of a day is an int number from 0 to 23,
        // while minutes and seconds are numbers from 0 to 59.
        // Nanoseconds can be any integer numbers from 0 to 999,999,999.
        LocalTime.of(24, 1, 1); // it throws DateTimeException (24 is an invalid value for hours)

        // It's also possible to create an instance of LocalTime by using static methods ofSecondOfDay and ofNanoOfDay.
        LocalTime time = LocalTime.ofSecondOfDay(12345); // 03:25:45
        LocalTime nanoTime = LocalTime.ofNanoOfDay(1234567890); // 00:00:01.234567890

        // There are some predefined constants in the LocalTime class as well :
        var min = LocalTime.MIN; // 00:00
        var max = LocalTime.MAX; // 23:59:59.999999999
        var noon = LocalTime.NOON; // 12:00
        var midnight = LocalTime.MIDNIGHT; // 00:00
    }

    public static void hoursMinutesAndSeconds() {
        LocalTime time = LocalTime.of(11, 45, 30, 999); // 11:45:30.000000999
        System.out.println(time);

        time.getHour();   // 11
        time.getMinute(); // 45
        time.getSecond(); // 30
        time.getNano();   // 999, nanoseconds

        System.out.println(time.toSecondOfDay()); // 42330
        System.out.println(time.toNanoOfDay()); // 42330000000999
    }

    public static void arithmeticMethods() {
        LocalTime time = LocalTime.of(11, 45, 30);

        LocalTime time1 = time.plusHours(5); // 16:45:30
        LocalTime time2 = time.plusHours(22); // 09:45:30
        LocalTime time3 = time.minusMinutes(10); // 11:35:30
        LocalTime time4 = time.minusSeconds(30); // 11:45

        time1 = time.withHour(23); // 23:45:30
        time2 = time.withMinute(50); // 9:50:30
        time3 = time.withSecond(0); // 11:35
    }
}

class MyLocalTimeExercise {
    public static void secondSinceStartADay() {
        Scanner scanner = new Scanner(System.in);
        var seconds = scanner.nextInt();

        var time = LocalTime.ofSecondOfDay(seconds);
        System.out.println(time);
    }
}

#########################################

	2.5. PeriodAndDurationClasses

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;

/**
 * The Period class represents a period of time by years, months, and days. If the unit includes all metrics, its unit
 * format is P{year}Y{month}M{day}D, where {year}, {month} and {day} are placeholders for values.
 * <p>
 * Duration represents a period of time storing the value in seconds and nanoseconds.Units of this class are created in
 * the same way as the units of Period and have a similar unit format PT{hour}H{minute}M{second}S when the unit includes
 * all metrics.
 *
 */

public class PeriodAndDurationClasses {

    public static void creatingPeriodUnits() {
        // The first and probably the most common way of creating Period units is by using the of() static method.
        Period period = Period.of(1995, 5, 23);
        System.out.println(period); // P1995Y5M23D

        // The next method allows us to get a Period unit in the form of a difference between two dates.
        // It will show negative values if the second argument is smaller, zero if they are equal, and a positive value
        // if the second argument is larger.
        LocalDate startDate = LocalDate.of(1995, 5, 23);
        LocalDate endDate = LocalDate.of(1995 , 8, 25);
        period = Period.between(startDate, endDate);
        System.out.println(period); // P3M2D

        // Another method accepts a text and parses it to a Period type.
        // 23 days
        System.out.println(Period.parse("P23D")); // P23D
        // 5 months 23 days
        System.out.println(Period.parse("P5M23D")); // P5M23D
        // -1995 years 5 months 23 days
        System.out.println(Period.parse("P-1995Y5M23D")); // P-1995Y5M23D

        // -23 days
        System.out.println(Period.parse("P-23D")); // P-23D
        // -5 months -23 days
        System.out.println(Period.parse("P-5M-23D")); // P-5M-23D
        // -1995 years -5 months -23 days
        System.out.println(Period.parse("P-1995Y-5M-23D")); // P-1995Y-5M-23D
        // -1995 years -5 months -23 days
        System.out.println(Period.parse("-P1995Y5M23D")); // P-1995Y-5M-23D
    }

    public static void extractingPeriodUnits() {
        Period period  = Period.of(1995, 5, 23);

        System.out.println(period.getYears()); // 1995
        System.out.println(period.getMonths()); // 5
        System.out.println(period.getDays()); // 23

        System.out.println(period.get(ChronoUnit.YEARS)); // 1995
        System.out.println(period.get(ChronoUnit.MONTHS)); // 5
        System.out.println(period.get(ChronoUnit.DAYS)); // 23
        // Note that ChronoUnit has fields for other units too, but the scope of this method only allows using the three
        // of them mentioned above. If you use a unit such as ChronoUnit.WEEKS or any other, you will face an
        // UnsupportedTemporalTypeException.
    }

    public static void operatingWithPeriodUnits() {
        Period period = Period.of(1, 1, 1);

        System.out.println(period.addTo(LocalDate.of(1995, 5, 23))); // 1996-06-24
        System.out.println(period.subtractFrom(LocalDate.of(1995, 5, 23))); // 1994-04-22
        System.out.println(period); // P1Y1M1D

        System.out.println(period.plus(Period.of(1995, 5, 23))); // P1996Y6M24D
        System.out.println(period.minus(Period.of(1995, 5, 23))); // P-1994Y-4M-22D
        System.out.println(period); // P1Y1M1D

        // The subtractFrom() method subtracts a period variable from a LocalDate
        // while the minus() subtracts the second Period unit from the first one.
    }

    public static void creatingDurationUnits() {
        Duration durationOf = Duration.of(3, ChronoUnit.DAYS);
        Duration durationOf1 = Duration.of(3, ChronoUnit.MINUTES);
        Duration durationOf2 = Duration.of(3, ChronoUnit.NANOS);

        System.out.println(durationOf); // PT72H
        System.out.println(durationOf1); // PT3M
        System.out.println(durationOf2); // PT0.000000003S

        // between
        LocalTime startTime = LocalTime.of(11, 45, 30);
        LocalTime endTime = LocalTime.of(12, 50, 30);
        System.out.println(Duration.between(startTime, endTime)); // PT1H5M

        // parse
        Duration duration1 = Duration.parse("PT1H20M");
        Duration duration2 = Duration.parse("PT30M");
        System.out.println(duration1); // PT1H20M
        System.out.println(duration2); // PT30M
    }

    public static void extractingDurationUnits() {
        System.out.println(Duration.of(1, ChronoUnit.DAYS).getSeconds()); // 86400
        System.out.println(Duration.of(1, ChronoUnit.HOURS).getSeconds()); // 3600
        System.out.println(Duration.of(90, ChronoUnit.MINUTES).getSeconds()); // 5400
        System.out.println(Duration.of(90, ChronoUnit.SECONDS).getSeconds()); // 90
        System.out.println(Duration.of(90, ChronoUnit.SECONDS).getNano()); // 0
        System.out.println(Duration.of(90, ChronoUnit.NANOS).getNano()); // 90

        // It has two methods operating on specified units: getSeconds() and getNano(), each returning its component in
        // a unit. So, if the unit contains both seconds and nanoseconds, getSeconds() will return only seconds and the
        // second one will return only nanoseconds.
        Duration duration = Duration.ofSeconds(3675, 75);

        System.out.println(duration); // PT1H1M15.000000075S
        System.out.println(duration.getSeconds()); // 3675
        System.out.println(duration.getNano()); // 75

        // Also, you can use the get() method if you don't want to specify the unit explicitly but pass the required
        // unit as an argument when calling it:
        duration = Duration.of(10, ChronoUnit.MINUTES);
        System.out.println(duration.get(ChronoUnit.SECONDS)); // 600
        // Like the similar method from the Period class, it will throw an exception if you pass an unsupported unit.
    }

    public static void operatingWithDurationUnits() {
        Duration duration = Duration.of(90, ChronoUnit.MINUTES);

        System.out.println(duration.addTo(LocalTime.of(19, 5, 23))); // 20:35:23
        System.out.println(duration.subtractFrom(LocalTime.of(19, 5, 23))); // 17:35:23
        System.out.println(duration); // PT1H30M

        System.out.println(duration.plus(Duration.of(10, ChronoUnit.MINUTES))); // PT1H40M
        System.out.println(duration.minus(Duration.of(10, ChronoUnit.MINUTES))); // PT1H20M
        System.out.println(duration); // PT1H30M
    }

    public static void main(String[] args) {

    }
}

class PeriodAndDurationClassesExercise {

    public static void addToMethod() {
        Period period  = Period.of(1, 1, 1);
        System.out.println(period.addTo(LocalDate.of(2000, 2, 22))); // 2001-03-23

        Duration duration = Duration.of(75, ChronoUnit.MINUTES);
        System.out.println(duration.addTo(LocalTime.of(20, 2, 22)));
    }
}

############################################

	2.6. ZonedDateTimeAndOffsetDateTime

import java.time.*;
import java.time.zone.ZoneRules;

public class ZonedDateTimeAndOffsetDateTime {

    public static void main(String[] args) {
//        classesDescribingTimeZones();
//        creatingRequiredObjects();
        performingOperations();
    }

    public static void classesDescribingTimeZones() {
        // The ZoneId class doesn't just show the current rules of the time zone but also past rules. For instance,
        // as of 2022, Armenia doesn't use daylight saving time but in 1999 it used
        LocalDateTime pastSummerTime = LocalDateTime.of(1999, 9, 15, 13, 00);
        LocalDateTime pastWinterTime = LocalDateTime.of(1999, 1, 15, 13, 00);

        LocalDateTime summerTime2022 = LocalDateTime.of(2022, 9, 15, 13, 00);
        LocalDateTime winterTime2022 = LocalDateTime.of(2022, 1, 15, 13, 00);

        System.out.println(pastSummerTime.atZone(ZoneId.of("Asia/Yerevan"))); // 1999-09-15T13:00+05:00[Asia/Yerevan]
        System.out.println(summerTime2022.atZone(ZoneId.of("Asia/Yerevan"))); // 2022-09-15T13:00+04:00[Asia/Yerevan]

        System.out.println(pastWinterTime.atZone(ZoneId.of("Asia/Yerevan"))); // 1999-01-15T13:00+04:00[Asia/Yerevan]
        System.out.println(winterTime2022.atZone(ZoneId.of("Asia/Yerevan"))); // 2022-01-15T13:00+04:00[Asia/Yerevan]

        // As you can see, there is a difference in the time zone in the two years. Now let's understand how the ZoneId
        // class gets the information about time zones:
        LocalDateTime  past = LocalDateTime.of(1999, 9, 15, 13, 00);
        LocalDateTime  by2022 = LocalDateTime.of(2022, 9, 15, 13, 00);
        ZoneRules rules = ZoneId.of("Asia/Yerevan").getRules();

        System.out.println(rules);
        System.out.println("Fixed Offset: " + rules.isFixedOffset()); // Fixed Offset: false
        System.out.println("Past summer offset: "  + rules.getOffset(past)); // Past summer offset: +05:00
        System.out.println("Current summer offset: "  + rules.getOffset(by2022)); // Current summer offset: +04:00

        // ZoneOffset represents the fixed offset of the time zone. Its value can vary depending on the time of year if
        // the specified region uses the daylight saving time approach.
        ZoneOffset zoneOffset = ZoneOffset.of("+04:00");
        ZoneOffset zoneOffsetHours = ZoneOffset.ofHours(4);
        ZoneOffset zoneOffsetHoursMinutes = ZoneOffset.ofHoursMinutes(4, 30);
        // ZoneOffset extends ZoneId and describes the amount of time the given time zone differs from Greenwich time.
        // Just like one region can have several offsets, one offset can represent several regions (countries, cities).

        // Note that there are regions where the offset contains not only hours but also minutes:
        System.out.println(ZoneId.of("Iran").getRules()); // Iran ZoneRules[currentStandardOffset=+03:30]
        System.out.println(ZoneId.of("Asia/Kolkata").getRules()); // ZoneRules[currentStandardOffset=+05:30]
    }

    public static void creatingRequiredObjects() {
        LocalDate localDate = LocalDate.of(1991, 4, 15);
        LocalTime localTime = LocalTime.of(18,30);

        LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
        ZoneId zoneId = ZoneId.of("Asia/Yerevan");
        ZoneOffset zoneOffset = ZoneOffset.of("+04:00");

        System.out.println(ZonedDateTime.of(localDate, localTime, zoneId)); // 1991-04-15T18:30+04:00[Asia/Yerevan]
        System.out.println(ZonedDateTime.ofInstant(Instant.EPOCH, zoneId)); // 1970-01-01T04:00+04:00[Asia/Yerevan]

        System.out.println(OffsetDateTime.of(localDateTime, zoneOffset)); // 1991-04-15T18:30+04:00
        System.out.println(OffsetDateTime.ofInstant(Instant.EPOCH, zoneId)); // 1970-01-01T04:00+04:00

        ZonedDateTime zonedDateTime1 = ZonedDateTime.from(OffsetDateTime.now());
        // Can co thong tin ve ZoneId
        ZonedDateTime zonedDateTime2 = ZonedDateTime.from(Instant.now().atZone(ZoneId.of("Asia/Yerevan")));

        OffsetDateTime offsetDateTime1 = OffsetDateTime.from(ZonedDateTime.now());
        // Can co thong tin ve ZoneOffset
        OffsetDateTime offsetDateTime2 = OffsetDateTime.from(LocalDateTime.now().atOffset(zoneOffset));

        ZonedDateTime.parse("1991-04-15T18:30+04:00[Asia/Yerevan]");
        OffsetDateTime.parse("1970-01-01T04:00+04:00");
    }

    public static void performingOperations() {
        // isBefore and isAfter
        LocalDate localDate = LocalDate.of(1991, 4, 15);
        LocalTime localTime = LocalTime.of(18,30);
        LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);

        ZoneId zoneId = ZoneId.of("Asia/Yerevan");
        ZoneOffset zoneOffset = ZoneOffset.from(LocalDateTime.now().atZone(zoneId));

        // unit1.toInstant().isBefore(unit2.toInstant())
        ZonedDateTime.of(localDateTime, zoneId).isBefore(ZonedDateTime.of(LocalDateTime.now(), zoneId));
        // unit1.toInstant().isAfter(unit2.toInstant())
        ZonedDateTime.of(localDateTime, zoneId).isAfter(ZonedDateTime.of(LocalDateTime.now(), zoneId));

        // unit1.toInstant().isBefore(unit2.toInstant())
        OffsetDateTime.of(localDateTime, zoneOffset).isBefore(OffsetDateTime.of(LocalDateTime.now(), zoneOffset));
        // unit1.toInstant().isAfter(unit2.toInstant())
        OffsetDateTime.of(localDateTime, zoneOffset).isAfter(OffsetDateTime.of(LocalDateTime.now(), zoneOffset));


        // compareTo()
        // For the ZonedDateTime units it operates as expected, returning -1, 0 or 1
        // but, when operating with OffsetDateTime units, it returns the difference in years
        LocalDate localDate1 = LocalDate.of(1991, 4, 15);
        LocalTime localTime1 = LocalTime.of(18,30);

        LocalDate localDate2 = LocalDate.of(1995, 5, 21);
        LocalTime localTime2 = LocalTime.of(18,30);

        LocalDateTime localDateTime1 = LocalDateTime.of(localDate1, localTime1);
        LocalDateTime localDateTime2 = LocalDateTime.of(localDate2, localTime2);

        zoneOffset = ZoneOffset.of("+04:00");

        OffsetDateTime offsetDateTime1 = OffsetDateTime.of(localDateTime1, zoneOffset);
        OffsetDateTime offsetDateTime2 = OffsetDateTime.of(localDateTime2, zoneOffset);

        System.out.println(offsetDateTime1.compareTo(offsetDateTime2)); // -4
        System.out.println(offsetDateTime2.compareTo(offsetDateTime1)); // 4


        // equals() va isEqual()
        // When comparing by the isEqual() method, you compare moments on the timeline where the time zone doesn't matter.
        // As for comparing by equals(), it requires comparison by all the field values of the object
        localDate = LocalDate.of(1991, 4, 15);
        localTime = LocalTime.of(18,30);
        localDateTime = LocalDateTime.of(localDate, localTime);

        zoneId = ZoneId.of("Asia/Yerevan");
        zoneOffset = ZoneOffset.from(LocalDateTime.now().atZone(zoneId));
        System.out.println(zoneId); // Asia/Yerevan
        System.out.println(zoneOffset);  // +04:00

        ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime, zoneOffset);
        ZonedDateTime zonedDateTime2 = ZonedDateTime.of(localDateTime, zoneId);
        System.out.println(zonedDateTime1); // 1991-04-15T18:30+04:00
        System.out.println(zonedDateTime2); // 1991-04-15T18:30+04:00[Asia/Yerevan]

        System.out.println(zonedDateTime1.equals(zonedDateTime2)); // false
        System.out.println(zonedDateTime1.isEqual(zonedDateTime2)); // true

        offsetDateTime1 = OffsetDateTime.ofInstant(Instant.ofEpochSecond(0), ZoneOffset.of("+03:00"));
        offsetDateTime2 = OffsetDateTime.ofInstant(Instant.EPOCH, zoneId);
        System.out.println(offsetDateTime1); // 1970-01-01T03:00+03:00
        System.out.println(offsetDateTime2); // 1970-01-01T04:00+04:00

        System.out.println(offsetDateTime1.equals(offsetDateTime2)); // false
        System.out.println(offsetDateTime1.isEqual(offsetDateTime2)); // true


        // get() methods
        // minus(), plus() and until() methods.
        ZoneId zone0 = ZoneId.of("GMT+0");
        ZoneId londonZone = ZoneId.of("Europe/London");
        ZoneId yerevanZone = ZoneId.of("Asia/Yerevan");
        ZoneOffset offset0 = ZoneOffset.of("+00:00");
        ZoneOffset londonOffset = ZoneOffset.of("+01:00");
        ZoneOffset yerevanOffset = ZoneOffset.of("+04:00");

        localDateTime = LocalDateTime.of(1991, 4, 15, 13, 00);
        ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, yerevanZone); // 1991-04-15T13:00+04:00[Asia/Yerevan]
        OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, yerevanOffset); // 1991-04-15T13:00+04:00

        System.out.println(zonedDateTime.getYear());
        System.out.println(zonedDateTime.getZone());
        System.out.println(zonedDateTime.getOffset());
        System.out.println(offsetDateTime.getHour());
        System.out.println(offsetDateTime.getOffset());


        // withZoneSameInstant() and withZoneSameLocal()
        // In practice, you will face situations where you will need to get a date-time unit from another unit by
        // changing the time zone.
        System.out.println(zonedDateTime.withZoneSameInstant(zone0)); // 1991-04-15T09:00Z[GMT]
        System.out.println(zonedDateTime.withZoneSameInstant(londonZone)); // 1991-04-15T10:00+01:00[Europe/London]
        System.out.println(zonedDateTime.withZoneSameLocal(londonZone)); // 1991-04-15T13:00+01:00[Europe/London]
        // The withZoneSameInstant() returns the copy of the unit by calculating its instant and changing the time zone
        // and withZoneSameLocal() returns the copy of the same date and time but with a changed time zone.
    }
}

#############################################

javacore.data.collections

1. framework
	Overview

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

/**
 * The Collections framework includes:
 * 1. interfaces that represent different types of collections;
 * 2. legacy implementations from earlier releases (known as "old collections");
 * 3. special-purpose implementations (like immutable collections);
 * 4. algorithms represented by static methods that perform useful operations on collections.
 */

/*
 * Commonly used interfaces
 *
 *                  Interface Collection                            InterfaceMap
 *        ___________________|_______________________                     |
 *        |                  |                      |                     |
 *  Interface List      Interface Set         Interface Queue     Interface SortedMap
 *                           |                      |
 *                      Interface SortedSet   Interface Deque
 *
 * The Map<K,V> interface is not a subtype of the Collection interface, but maps are often considered as collections
 * since they are part of the collections framework and have similar methods.
 */

public class Overview {

    public static void theCollectionInterface() {
        // Here are common methods provided by the Collection interface.
        // int size() returns the number of elements in this collection;
        // boolean isEmpty() returns true if this collection contains no elements;
        // boolean contains(Object o) returns true if this collection contains the specified element;
        // boolean add(E e) adds an element to the collection. Returns true, if the element was added, else returns false;
        // boolean remove(Object o) removes a single instance of the specified element;
        // boolean removeAll(Collection<?> collection) removes elements from this collection that are also contained in the specified collection;
        // void clear() removes all elements from this collection.

        // It is possible to refer to any particular collection via this base interface since
        Collection<String> languages = new ArrayList<>();

        languages.add("English");
        languages.add("Deutsch");
        languages.add("Français");

        System.out.println(languages.size()); // 3

        // This approach allows you to replace the concrete collection at any time without changing the code that uses it.

    }

    public static void mutableAndImmutableCollections() {
        // All collections can be divided into two large groups: mutable and immutable. They both implement the
        // Collection<E> interface, but immutable collections will throw an UnsupportedOperationException when you try
        // to invoke some methods which change them: for example, add, remove, clear.
    }

    public static void iteratingOverCollection() {
        // If you would like to iterate over all elements of any collection, you can use the for-each style loop.
        Collection<String> languages = new ArrayList<>();

        languages.add("English");
        languages.add("Deutsch");
        languages.add("Français");

        for (String lang : languages) {
            System.out.println(lang);
        }

        // If you are already familiar with method references or lambda expressions, you can use another style for
        // iterations using the forEach(Consumer<T> consumer) method:
        languages.forEach(System.out::println); // with method reference
        languages.forEach(elem -> System.out.println(elem)); // with lambda expression
    }

    public static void removingElements() {
        Collection<String> languages = new ArrayList<>();

        languages.add("English");
        languages.add("Deutsch");
        languages.add("Français");

        // It is also possible to remove elements from a mutable collection (like ArrayList).
        languages.remove("Deutsch");

        System.out.println(languages.size()); // 2

        // if you are already familiar with lambda expressions, you can invoke the removeIf method to remove all of the
        // elements that satisfy the given predicate:
        languages.removeIf(lang -> lang.startsWith("E")); // it removes English

        System.out.println(languages.size()); // 1
    }

    public static void main(String[] args) {
        Integer[] arr = {1, 2, 4};
        System.out.println(Arrays.toString(ArrayUtils.invert(arr)));
    }
}

class ArrayUtils {

    public static <T> T[] invert(T[] arr) {
        T[] reserveArr = Arrays.copyOf(arr, arr.length);
        for (int i = 0; i < arr.length; i++) {
            reserveArr[i] = arr[arr.length - 1 - i];
        }

        return reserveArr;
    }
}

###########################################
	
2. implementation
	IntroCollections

import java.util.ArrayList;

/**
 * Collections are more sophisticated and flexible than arrays.
 * First of all, they are resizable: you can add any number of elements to a collection. A collection will
 * automatically handle the deletion of an element from any position.
 * The second point is collections provide a rich set of methods that are already implemented for you.
 */

public class IntroCollections {

    public static void theSimplestCollectionExample() {
        ArrayList<String> list = new ArrayList<>();

        list.add("first");
        list.add("second");
        list.add("third");

        System.out.println(list); // [first, second, third]

        System.out.println(list.get(0)); // first
        System.out.println(list.get(1)); // second
        System.out.println(list.get(2)); // third

        list.remove("first");

        System.out.println(list); // [second, third]

        System.out.println(list.size()); // 2

        // Note, in this example, we used the get method to access an element by its index. Unlike arrays, collections
        // do not have the [] operator.
    }

    public static void main(String[] args) {

    }
}
Leave a Comment