Friday, April 10, 2020

Java 13+'de Karakter Katarı Bloğu (=Text Blocks) Kullanımı

String sınıfını karakter katarlarını tanımlamak için kullanıyoruz. Bu karakter katarını iki farklı şekilde oluşturabiliriz:
  1. Karakter katarı kodlama zamanında bellidir:
    String fullname = "Jack Bauer";
  2. Karakter katarı bir hesaplama sonucunda dinamik olarak üretilecektir:
    public class DynamicString {
        public static void main(String[] args) {
            var s = "";
            for (var i = 0; i < 1_000_000; ++i) {
                s += i;
            }
            System.out.println(s.length());
            var sb = new StringBuilder();
            for (var i = 0; i < 1_000_000; ++i) {
                sb.append(i);
            }
            System.out.println(sb.length());
            var ss = IntStream.range(0, 1_000_000)
                    .boxed()
                    .map(Object::toString)
                    .collect(Collectors.joining());
            System.out.println(ss.length());
        }
    }
    
    Eğer karakter katarı dinamik olarak üretilecekse onu String yerine StringBuilder ya da Stream kullanarak üretmek başarım açısından daha doğru olacaktır. Yukarıdaki kod parçasında her üç yapıda (String, StringBuilder ve Stream) aynı sonucu üretecektir. ancak ikinci ve üçüncü yapılar (StringBuilder ve Stream) kısa sürede sonlanacaktır.
Karakter katarının birden fazla satıra yayıldığı durumlarda ilklendirmeyi bitiştirme (+) operatörü kullanarak kodlamak hataya açık ve can sıkıcı olabilir:
private static final String SELECT_CUSTOMERS_BY_IDENTITY2 = 
            "SELECT IDENTITY, FULLNAME, EMAIL, PHONE " 
            + "FROM CUSTOMERS "
            + "WHERE IDENTITY=?";
Java 13 ile birlikte bu şekilde birden fazla satıra yayılan karakter katarlarını """ arasında birden fazla satıra yayılacak şekilde serbest bir şekilde yazabiliyoruz:
public class UseTextBlocks1 {
    private static final String SELECT_CUSTOMERS_BY_IDENTITY = """
            SELECT IDENTITY, FULLNAME, EMAIL, PHONE
            FROM CUSTOMERS
            WHERE IDENTITY=?
            """;
    private static final String JACK_AS_JSON = """
            {
                "identity": "12345678910",
                "fullname": "jack bauer",
                "email": "jack.bauer@ctu.gov",
                "phone" : "555-555-5555"
            }
            """;
    private static final String JACK_AS_XML = """
            <?xml version="1.0"?>
            <customers>
                <customer identity="12345678910">
                    <fullname>jack bauer</fullname>
                    <email>jack.bauer@ctu.gov</email>
                    <phone>555-555-5555</phone>
                </customer>
            </customers>
            """;

    public static void main(String[] args) {
        System.out.println(SELECT_CUSTOMERS_BY_IDENTITY);
        System.out.println(JACK_AS_JSON);
        System.out.println(JACK_AS_XML);
    }
}

Bu uygulama çalıştırıldığında konsolda aşağıdaki gibi bir çıktı oluşacaktır:
SELECT IDENTITY, FULLNAME, EMAIL, PHONE
FROM CUSTOMERS
WHERE IDENTITY=?

{
    "identity": "12345678910",
    "fullname": "jack bauer",
    "email": "jack.bauer@ctu.gov",
    "phone" : "555-555-5555"
}

<?xml version="1.0"?>
<customers>
    <customer identity="12345678910">
        <fullname>jack bauer</fullname>
        <email>jack.bauer@ctu.gov</email>
        <phone>555-555-5555</phone>
    </customer>
</customers>

Birden fazla satıra yayılan bir başka örnek için aşağıdaki kodu inceleyelim:
import javax.script.Invocable;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.List;
import java.util.function.Function;

public class ScriptingApiExample {
    private static final Function<Double, Double> gun = x -> 2 * x;

    public static void main(String[] args) throws ScriptException {
        var sem = new ScriptEngineManager();
        var jsEngine = sem.getEngineByExtension("js");
        jsEngine.eval("""
                var apply = function(x) { 
                return 2 * x * x + 3 * x + 7 ; 
                }
                """);
        Function<Double, Double> fun = ((Invocable) jsEngine).getInterface(Function.class);
        var numbers = List.of(4., 8., 15., 16., 23., 42.);
        numbers.stream().map(fun).forEach(System.out::println);
        jsEngine.eval("""
                var apply = function(x) { 
                return x * x + 2 * x + 1 ; 
                }
                """);
        numbers.stream().map(fun).forEach(System.out::println);
        numbers.stream().map(gun).forEach(System.out::println);
    }
}

Evet, Java kodunun içinde bir String değişkende JavaScript kodunu saklayabiliriz! Hatta saklamak ile kalmayıp çalıştırabiliriz de! 

Java 14'de karakter katarı blokları ile ilgili iki yenilik bulunuyor. İlk yenilik, karakter katarı bloğunun tek bir satır olarak ele alınmasını sağlayan, \ karakterinin satır sonunda kullanımıdır:

public class UseTextBlocks2 {
    private static final String SELECT_CUSTOMERS_BY_IDENTITY = """
            SELECT IDENTITY, FULLNAME, EMAIL, PHONE\
            FROM CUSTOMERS\
            WHERE IDENTITY=?\
            """;
    private static final String JACK_AS_JSON = """
            {\
                "identity": "12345678910",\
                "fullname": "jack bauer",\
                "email": "jack.bauer@ctu.gov",\
                "phone" : "555-555-5555"\
            }\
            """;
    private static final String JACK_AS_XML = """
            <?xml version="1.0"?>\
            <customers>\
                <customer identity="12345678910">\
                    <fullname>jack bauer</fullname>\
                    <email>jack.bauer@ctu.gov</email>\
                    <phone>555-555-5555</phone>\
                </customer>\
            </customers>\
            """;

    public static void main(String[] args) {
        System.out.println(SELECT_CUSTOMERS_BY_IDENTITY);
        System.out.println(JACK_AS_JSON);
        System.out.println(JACK_AS_XML);
    }
}

Bu uygulamayı çalıştırdığımızda konsolda aşağıdaki çıktı oluşacaktır:
SELECT IDENTITY, FULLNAME, EMAIL, PHONEFROM CUSTOMERSWHERE IDENTITY=?
{    "identity": "12345678910",    "fullname": "jack bauer",    "email": "jack.bauer@ctu.gov",    "phone" : "555-555-5555"}
<?xml version="1.0"?><customers>    <customer identity="12345678910">        <fullname>jack bauer</fullname>        <email>jack.bauer@ctu.gov</email>        <phone>555-555-5555</phone>    </customer></customers>

Çıktıdan anlaşıldığı gibi karakter katarı bloğu tek bir satırlık karakter katarı olarak işlem gördü. Java 14'de karakter katarı bloğu ile ilgili gelen ikinci yenilik satır sonundaki görünmeyen karakterlerin (=white space) korunmasına yönelik \s kullanımıdır. \s kullanımına ilişkin aşağıdaki örneği inceleyelim:

public class UseTextBlocks3 {

    private static final String JACK_AS_JSON1 = """
            {\u0020
                "identity": "12345678910",\s
                "fullname": "jack bauer",\s
                "email": "jack.bauer@ctu.gov",\s
                "phone" : "555-555-5555"\s
            }\s
            """;
    private static final String JACK_AS_JSON2 = """
            {\u0020\u0020
                "identity": "12345678910",\s
                "fullname": "jack bauer",\s
                "email": "jack.bauer@ctu.gov",\s
                "phone" : "555-555-5555"\s
            }\s
            """;
    private static final String JACK_AS_JSON3 = """
            {\u0020\u0020\u0020\s
                "identity": "12345678910",\s
                "fullname": "jack bauer",\s
                "email": "jack.bauer@ctu.gov",\s
                "phone" : "555-555-5555"\s
            }\s
            """;

    public static void main(String[] args) {
        System.out.println(JACK_AS_JSON1.length());
        System.out.println(JACK_AS_JSON2.length());
        System.out.println(JACK_AS_JSON3.length());
    }
}

Burada """ arasında verilen satırların sonundaki görünmeyen karakter otomatik olarak temizlenirken, satır sonunda \s kullanıldığında görünmeyen karakterler (boşluk, sekme gibi) korunacaktır. Yukarıdaki kodu çalıştırdığımızda ekran görüntüsü aşağıda verildiği şekilde oluşacaktır:

134
134
138

\u0020 değeri boşluk karakterinin Unicode karşılığıdır. Yukarıdaki ilk iki tanımlamadaki kullanımda satır sonundaki boşluk elendiği için String uzunlukları 134 oldu. Üçüncü tanımlamada ise üç adet boşluk ve sonunda \s kullanıldığı için String uzunluğu 138 oldu.

No comments:

Post a Comment