Kohei Nozaki's blog 

Array sorting with Java8 idioms


Posted on Sunday Jun 28, 2015 at 04:14PM in Java


Thanks to Java8, now we can write sorting with comparators in very simple idiom. assume we have a JavaBean named Stock as follows:

public class Stock {
    private final String symbol;
    private final LocalDate baseDate;
    private final int price;

    public Stock(String symbol, LocalDate baseDate, int price) {
        this.symbol = symbol;
        this.baseDate = baseDate;
        this.price = price;
    }
...

We have following dataset:

final Stock[] data = {
        new Stock("ORCL", LocalDate.of(2015, 3, 1), 10),
        new Stock("ORCL", LocalDate.of(2015, 3, 2), 11),
        new Stock("ORCL", LocalDate.of(2015, 3, 3), 12),
        new Stock("JAVA", LocalDate.of(2015, 3, 1), 100),
        new Stock("JAVA", LocalDate.of(2015, 3, 2), 110),
        new Stock("JAVA", LocalDate.of(2015, 3, 3), 120),
        new Stock("GOOG", LocalDate.of(2015, 3, 1), 1000),
        new Stock("GOOG", LocalDate.of(2015, 3, 2), 1001),
        new Stock("GOOG", LocalDate.of(2015, 3, 3), 1002),
};

How to get an array that sorted by symbol in ascending order, but baseDate in descending order when they have same symbol? the following code works:

Comparator<Stock> p1 = Comparator.comparing(Stock::getSymbol);
Comparator<Stock> p2 = Comparator.comparing(Stock::getBaseDate).reversed();
Comparator<Stock> p3 = p1.thenComparing(p2);
Arrays.sort(data, p3);

System.out.println(Arrays.toString(data));

The variable p1 stores a Comparator that sorts beans with symbol, and p2 does the same for baseDate but in reversed order, and p3 stores a composit comparator for these two. also you can add more comparators with code like .thenComparing(p4).thenComparing(p5)…​ as well. this yields the following output:

[Stock{symbol='GOOG', baseDate=2015-03-03, price=1002}
, Stock{symbol='GOOG', baseDate=2015-03-02, price=1001}
, Stock{symbol='GOOG', baseDate=2015-03-01, price=1000}
, Stock{symbol='JAVA', baseDate=2015-03-03, price=120}
, Stock{symbol='JAVA', baseDate=2015-03-02, price=110}
, Stock{symbol='JAVA', baseDate=2015-03-01, price=100}
, Stock{symbol='ORCL', baseDate=2015-03-03, price=12}
, Stock{symbol='ORCL', baseDate=2015-03-02, price=11}
, Stock{symbol='ORCL', baseDate=2015-03-01, price=10}
]


What I learned from the book Core Java for the Impatient


Posted on Friday Jun 19, 2015 at 06:07PM in Java


I’m reading a book named Core Java for the Impatient. I leave some notes that what I learned from that book.

Array construction

You can omit the new int[] statement when you declare a variable as follows:

int[] array = {1, 2, 3};

You can’t omit it when you don’t declare a variable at the same time (in other words, when you use an existing variable).

For example, the following is illegal:

int[] array;
array = {2, 3, 4};

You need to write like the following instead:

int[] array;
array = new int[]{2, 3, 4};

NumberFormat

The NumberFormat class provides some useful text formatting functions for numeric variables.

Currency formatting

final BigDecimal val1 = new BigDecimal("0.126");
final NumberFormat currencyInstance = NumberFormat.getCurrencyInstance(Locale.US);
System.out.println(currencyInstance.format(val1));

Yields:

$0.13

Percentage formatting

final BigDecimal val2 = new BigDecimal("0.126");
final NumberFormat percentInstance = NumberFormat.getPercentInstance(Locale.US);
System.out.println(percentInstance.format(val2));

Yields:

13%

They automatically adds the symbol and round up on 6 and round down on 5.

Wildcard for the classpath

Consider a class which depends on the class corejava.jar1.Foo and corejava.jar2.Bar:

package corejava.classpath;

public class Main {
    public static void main(String[] args) {
        System.out.println(new corejava.jar1.Foo());
        System.out.println(new corejava.jar2.Bar());
    }
}

You have these classes in separated three jar files in the /tmp/jar directory as follows:

$ ls -l /tmp/jar
total 24
-rw-r--r--  1 kyle  wheel  2192 Jun 19 16:06 classpath-1.0-SNAPSHOT.jar
-rw-r--r--  1 kyle  wheel  1962 Jun 19 16:04 jar1-1.0-SNAPSHOT.jar
-rw-r--r--  1 kyle  wheel  1962 Jun 19 16:04 jar2-1.0-SNAPSHOT.jar

In this setup, you can specify all of three jar files with the wildcard * as follows:

$ java -cp '/tmp/jar/*' corejava.classpath.Main
corejava.jar1.Foo@511d50c0
corejava.jar2.Bar@5e2de80c

Note that you can’t use complex wildcard that smarter UNIX shells recognize. in other words, it doesn’t recognize patterns like *.jar. for example, the following command won’t work:

$ java -cp '/tmp/jar/*.jar' corejava.classpath.Main
Error: Could not find or load main class corejava.classpath.Main

Including an image to javadoc

Consider you have a class named Dog in a Maven project. you want to include an image of a dog named chihuahua.jpg to the javadoc of the class. in such case you can write the class as follows:

package corejava.main;

/**
 * The class represents a dog. <br> <img src="doc-files/chihuahua.jpg" alt="a cute chihuahua dog">
 */
public class Dog {

    /**
     * The dog will say woof.
     */
    public void bark() {
        System.out.println("Woof!");
    }
}

Next, put the chihuahua.jpg in src/main/javadoc/corejava/main/doc-files. structure under the src/main will be:

.
|-- java
|   `-- corejava
|       `-- main
|           `-- Dog.java
|-- javadoc
|   `-- corejava
|       `-- main
|           `-- doc-files
|               `-- chihuahua.jpg
`-- resources

Then execute mvn javadoc:javadoc in the top of the project directory. javadoc will be produced in the target/site/apidocs directory. open index.html in that directory and go to the documentation of Dog class, you will see the image of a dog as follows:

a0e5b322 584d 4e5d a246 e6f824d1085c

Consider you have a class named Cat:

package corejava.main;

/**
 * Represents a cat.
 */
public class Cat {

    /**
     * The cat starts meowing.
     *
     * @see corejava.main.Dog#bark()
     * */
    public void meow() {
        System.out.println("Meow!");
    }
}

This produces the following javadoc:

34963f24 9e7f 4367 a56f b9a464553211

There are some of more useful syntaxes such as link to external URLs.

Method references

The following three statements produce identical Comparator:

Comparator<String> c1 = new Comparator<String>() {
    @Override
    public int compare(String x, String y) {
        return x.compareTo(y);
    }
};
Comparator<String> c2 = (x, y) -> x.compareTo(y);
Comparator<String> c3 = String::compareTo;

Constructor references

Constructor references are useful with Streams. consider you have a class named Dog:

public class Dog {
    private String name;

    public Dog(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Dog{" + "name='" + name + '\'' + '}';
    }
}

You can convert a List<String> that contains name of dogs to a Stream<Dog> as follows:

List<String> dogs = Arrays.asList("Snoopy", "Spike", "Olaf");
Stream<Dog> dogStream = dogs.stream().map(Dog::new);

If you need to create a typed array from that Stream<Dog>, you can use following idiom:

Dog[] dogArray = dogStream.toArray(Dog[]::new);