19 Ekim 2020 Pazartesi

ConcurrentHashMap.merge metodu - Atomic Metod

merge metodu - key + value + BiFunction
Bu metod Java 8 ile geldi. İlklendirme veya yeni değer hesaplama içindir.

compute() ve merge() ile Farkı
compute() metodu da aynı merge() gibidir. Eğer ilk değeri yoksa merge() ikinci parametre olarak belirtilen değeri kullanır. compute() ise ilk değer yoksa ikinci parametre olarak verilen BiFunction sonucunu kullanır.

Örnek
Şöyle yaparız. Anahtar yoksa, key,value=1 olarak ekler. Anahtar mevcutsa verilen BiFunction çalıştırılır.
private Integer somefunction() {
  return cache.merge(key, 1, Integer::sum);
}
Örnek
Şöyle yaparız. Çıktı olarak "GERB: 116" alırız
Map<String, Integer> voting = new ConcurrentHashMap<>();

for (int i = 0; i < 16; i++)
    new Thread(() -> {
        voting.merge("GERB", 1, Integer::sum);
    }).start();

for (int i = 0; i < 100; i++)
    voting.merge("GERB", 1, Integer::sum);

Thread.sleep(5000); // Waits for the threads to finish

for (String s : voting.keySet())
    System.out.println(s + ": " + voting.get(s));

13 Ekim 2020 Salı

Stream.Builder Arayüzü

Giriş
Bu arayüzün add() ve accept() isimli iki metodu var. accept() coid dönüyor. add() ise this dönüyor. Açıklaması şöyle
Stream.Builder extends Consumer<T> so it must implement the accept(T) method.

But accept(T) returns void, so I think they added add(T) for convenience: methods in a builder pattern implementation often return this to be able to chain the building and finally call build().
add metodu
Örnek
Şöyle yaparız
Stream<Task> getAll(){
  Stream.Builder<Task> all2 = Stream.builder();

  all2.add(item1);
  ..

  return all2.build();
}
Örnek
Bu sınıf bir koşula bağlı olarak stream'in yaratılmasını değiştirebilir. Şöyle yaparız
Stream.Builder<MyType> builder = Stream.builder();
builder.add(a).add(b);
if(someCondition) builder.add(c).add(d);
builder.add(e).build()
/* stream operations */
Aslında aynı şeyi bir ArrayList kullanarak ta yapmak mümkün. Ancak Strream.Builder lazy olduğu için daha az bellek kullanımına sebep olabilir.

6 Ekim 2020 Salı

Matcher Sınıfı

Giriş
Şu satırı dahil ederiz
import java.util.regex.Matcher;
Bu sınıfın ana kullanım amacı Capture Group'lara erişmek. Matcher nesnesi Pattern tarafından yaratılır

find metodu
Eşleşmeleri teker teker bulur.

Örnek
Şöyle yaparız.
String line = "XYZ Q|1|^123456<CR>";
Pattern queryRegex = Pattern.compile("Q\\|\\d\\|(.+?)<CR>");

Matcher queryMatcher=queryRegex.matcher(line);
if (queryMatcher.find()) {
    System.out.println("Group 0: " + queryMatcher.group(0));
    System.out.println("Group 1: " + queryMatcher.group(1));
}
İlk çıktı her zaman tüm eşleşmedir. İkinci sonuç ise ilk gruptur.
Group 0: Q|1|^123456<CR>
Group 1: ^123456
Örnek
Bazen find metodunu döngü içinde kullanmak gerekir.
String s = "...";
Matcher m = Pattern.compile("[^,()]+|\\([^)]*\\)").matcher(s);
while (m.find())
  System.out.println(m.group());
group metodu
group (0) değerini yani tüm eşleşmeyi verir.

Örnek
$...$ arasındaki kelimeleri bulmak için şöyle yaparız.
String x = "Hey my name is $name$; I have $years$ years old," + 
           "and I love play $sport$ and I live in $country$ !";
Pattern p = Pattern.compile("\\$\\w+\\$");
Matcher m = p.matcher(x);
Map<String, Integer> map = new LinkedHashMap<>();

while(m.find()) {
  String in = m.group().substring(1,m.group().length()-1);
  map.put(in, in.length());
}
Örnek
Şöyle yaparız.
Pattern p = Pattern.compile("(?<!\\d)\\d{2}:\\d{2}(?!\\d)");
Matcher m = pattern.matcher(inputString);

if (m.find()) {
    System.err.println("Time: " + m.group());
}
group metodu - int
Belirtilen yakalama grubunu döndürür.
Örnek
Elimizde şöyle bir string olsun.
String timeStr = "10:15:34";
Şöyle yaparız.
Pattern p = Pattern.compile("(\\d+):(\\d+):(\\d+)");
Matcher m = p.matcher(timeStr);
if (m.matches()) {
  int hours = Integer.parseInt(m.group(1));
  int minutes = Integer.parseInt(m.group(2));
  int seconds = Integer.parseInt(m.group(3));
  ...
}
groupCount metodu
Tüm eşleşen grupları verir. Şöyle yaparız.
String str="asd14sd67fgh007";
Pattern pattern = Pattern.compile("\\w+([0-9]+)\\w+([0-9]+)");
Matcher matcher = pattern.matcher(str);
for(int i = 0 ; i < matcher.groupCount(); i++) {
  matcher.find();
  System.out.println(matcher.group());
}
matches metodu
Verilen string ile düzenli ifadenin tam olarak eşleşip eşleşmediğini döner. C#'taki RegEx.IsMatch metodu ile aynıdır.
String s = "...";
Pattern pattern = Pattern.compile("...");

Matcher matcher = pattern.matcher(s);
// Check if pattern matches 
if (matcher.matches()) {
  ...
}  
quoteReplacement metodu
Açıklaması şöyle
Use Matcher.quoteReplacement(java.lang.String) to suppress the special meaning of these characters, if desired.
Örnek
Şöyle yaparız
String content = "<xxx.xx.name>xxx.xxx.com:111</xxx.xx.name>";
String destination = Matcher.quoteReplacement("${VAR}");
String source = "xxx.xxx.com:111";
content = content.replaceAll(source, destination);
Çıktı olarak şunu alırız
<xxx.xx.name>${VAR}</xxx.xx.name>
reset metodu
Ne işe yarar bilmiyorum. Şöyle yaparız.
Matcher matcher = ...;
matcher.reset();
results metodu
results metodu yazısına taşıdım

DateTimeFormatter Örüntü Sabitleri

Giriş
Sabitleri gösteren bir tablo burada.

Time of Day
"B" Java 17 ile geliyor.
Örnek
Şöyle yaparız
DateTimeFormatter timeOfDayFomatter = DateTimeFormatter.ofPattern("B");
System.out.println(timeOfDayFomatter.format(LocalTime.of(8, 0)));
System.out.println(timeOfDayFomatter.format(LocalTime.of(13, 0)));
System.out.println(timeOfDayFomatter.format(LocalTime.of(20, 0)));
System.out.println(timeOfDayFomatter.format(LocalTime.of(23, 0)));
System.out.println(timeOfDayFomatter.format(LocalTime.of(0, 0)));

// Output
in the morning
in the afternoon
in the evening
at night
midnight

Saat İçin Sabitler
a - am veya pm
Örnek
Açıklaması şöyle. Yani "a" kullanacaksak hangi locale olduğunu belirtmek gerekir.
You need to specify locale. Without it, 'AM' is not going to parse unless your platform default locale is english.
Şöyle yaparız
LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM",
  DateTimeFormatter.ofPattern("M/d/uuuu h:m:s a", Locale.ENGLISH));
n - nanosecond
nanosaniye. Kaç tane n yazmak lazım bilmiyorum.

h - Hour
AM/PM düzenine göre saat. Yani saat 0-12 arasındadır
Örnek
Şöyle yaparız
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("[EEEE ]ha", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt.format(formatter) + " -local date time with optnal day in format");
Çıktı olarak şunu alırız. Burada tek h kullanıldığı için çıktı 02 şeklinde değil.
Saturday 2PM -local date time with optnal day in format
H - Hour
24 saat düzenine göre saat. Yani saat 0-24 arasındadır

s - saniye
Açıklaması şöyle.
s second-of-minute number
S - milisaniye, microsaniye, nanosaniye
Açıklaması şöyle. Milisaniye 3 hanelidir.
S fraction-of-second fraction
Tarih İçin Sabitler
d - tek haneli sayı şeklindeki date
Gün tek haneli olacaktır.

dd - iki haneli sayı şeklindeki date
Gerekiyorsa gün 0 ile 2 hane olaak şekilde doldurulur (left pad'lenir)

EEE - Gün İsimle Olacaktır
Gün ismi Locale İngilizce ise Monday vs. olacaktır.

Örnek
Şöyle yaparız. Burada [EEE] ile optional gün ismi belirtiliyor. Gerçi LocalDateTime değil LocalTime parse ediliyor yani gün ismi boşa gidiyor ancak iyi bir örnek
String dateTxt = "Monday 5AM";
//for parsing day of week is ignored
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("[EEEE ]ha", Locale.ENGLISH);
LocalTime lt = LocalTime.parse(dateTxt, formatter);
System.out.println(lt + " - parsed local time ");
Çıktı olarak şunu alırız
05:00 - parsed local time 
Örnek
Şöyle yaparız
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("[EEEE ]ha", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt.format(formatter) + " -local date time with optnal day in format");
Çıktı olarak şunu alırız
Saturday 2PM -local date time with optnal day in format
M - tek haneli sayı şeklindeki month
Ay tek haneli olacaktır.

MM - iki haneli sayı şeklindeki month
Gerekiyorsa ay 0 ile 2 hane olacak şekilde doldurulur (left pad'lenir)

MMM - isim ile month
Ay
Örnek
Şöyle yaparız
// the date String
String d = "16 Apr 2020";
// which is parsed to a LocalDate using a formatter with a suitable pattern
LocalDate ld = LocalDate.parse(d, DateTimeFormatter.ofPattern("dd MMM yyyy"));
// then printed in a different format using a formatter with a differen pattern
System.out.println(ld.format(DateTimeFormatter.ofPattern("dd-MM-yyyy")));
Çıktı olarak şunu alırız
16-04-2020
u - year
Yıl : y'den farklı olarak "of no specific era" anlamına gelir. Açıklaması şöyle
yyyy or uuuu rarely matters, but note that this mean 4 digits are required. The difference kicks in for years before 0: uuuu goes negative, yyyy does not and expects you to use e.g. GG so that you get 44 BC instead of -44
Örnek
Şöyle yaparız
String dateTime = "02 Sep 2020 12:24 AM";
DateTimeFormatter parserDtf = DateTimeFormatter.ofPattern("dd MMM uuuu hh:mm a",
                                                                Locale.ENGLISH);
DateTimeFormatter outputDtf = DateTimeFormatter.ofPattern("dd MMM uuuu 'at' hh:mm a",
                                                                Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(dateTime, parserDtf);
System.out.println(ldt.format(outputDtf));
Çıktı olarak şunu alırız
02 Sep 2020 at 12:24 AM
w - week
Hafta sayısı

y - year
Yıl : u ile farkını yukarıya yazdım

Y - year
Yıl : week-base year.

Saat ve Tarih Ayracı
'T'
String içindeki T alanını temsil eder. Şöyle yaparız.
DateTimeFormatter inputFormatter = DateTimeFormatter
  .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH);
DateTimeFormatter outputFormatter = DateTimeFormatter
  .ofPattern("dd-MM-yyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse("2018-04-10T04:00:00.000Z", inputFormatter);
String formattedDate = outputFormatter.format(date);
System.out.println(formattedDate); // prints 10-04-2018
Zaman Dilimi
X - UTC Offset Belirtir
Örnek
Açıklaması şöyle.
The X on the end allows for either a Z or an offset-from-UTC such as -08 or -0830 or -08:30 or -083015 or -08:30:15.
Elimizde şöyle bir kod olsun
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMdd'T'HHmmssX")
  .withResolverStyle(ResolverStyle.STRICT);

boolean isParseableBasicIso8601(String str) {
  try {
    OffsetDateTime odt = OffsetDateTime.parse(str, formatter);
    return odt.getOffset().equals(ZoneOffset.UTC);
  } catch (DateTimeParseException dtpe) {
    return false;
  }
}
Şöyle yaparız
String[] testStrings = {
  "20210223T234556Z",
  "Cannot be parsed",
  "20210229T234556Z",
  "20210223T234556+08",
  "20210223T234556+00",
};
    
for (String s : testStrings) {
  System.out.format("%-18s? %s%n", s, isParseableBasicIso8601(s));
}
Çıktı olarak şunu alırız. X ile "Z", "+08", "+00" gibi saat dilimleri parse edilebilmiş.  
20210223T234556Z  ? true
Cannot be parsed  ? false
20210229T234556Z  ? false
20210223T234556+08? false
20210223T234556+00? true
Optional Alanlar
[] karakterleri arasında belirtilir.

Örnek
Şöyle yaparız. Burada string içinde Z zaten yoktur ancak optional olduğu için hata almayız.
LocalDateTime dateTime = LocalDateTime.parse("2017-01-17 09:28:45",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss['Z']"));
Örnek
Açıklaması şöyle.
The square brackets mean optional. We accommodate either a dot or comma. Note the singular digit for fraction of second. The X on the end allows for either a Z or an offset-from-UTC such as -08 or -0830 or -08:30 or -083015 or -08:30:15.
Şöyle yaparız. Bu aslında 2009-08-13T14:56:07Z şeklindedir.
String input = "20090813145607.0Z";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "uuuuMMddHHmmss[,S][.S]X" );
OffsetDateTime odt = OffsetDateTime.parse ( input , f );
Instant instant = odt.toInstant ();