30 Mayıs 2019 Perşembe

Pattern Sınıfı

Giriş
Düzenli İfade (Regular Expression veya RegEx) için temel sınıftır.

compile metodu - string
Verilen düzenli ifadeyi bir nesne haline getirir.
Pattern pattern = Pattern.compile("...");
Gördüğüm örnekler
AlphaNumeric = [A-Za-z\\d]+
Numeric = \\d+
Spaces = [ \t]+
Date in DD-MM-YYY =([012]\\d|3[01])-(0\\d|1[012])-(\\d{4})
compile metodu - string + flag
Şöyle yaparız.
Pattern pattern =Pattern.compile("...", Pattern.CASE_INSENSITIVE);
asPredicate metodu
asPredicate metodu yazısına taşıdım

matcher metodu
Matcher döner. Girdi ile düzenli ifadeyi eşleştirir.
String line = "...";
Pattern pattern=Pattern.compile("...");
Matcher matcher=pattern.matcher(line);
splitAsStream metodu
splitAsStream metodu yazısına taşıdım

Diğer
1. Look Ahead ve Look Behind
Açıklaması şöyle.
(?<!\d)  # negative lookbehind to assert previous char is not a digit
\d{2}    # match exact 2 digits
:        # match a colon
\d{2}    # match exact 2 digits
(?!\d)   # negative lookahead to assert next char is not a digit
Negative Lookahead
Belirtilen şey ile başlamayan anlamına gelir.
Örnek
Şöyle yaparız. Burada amaç sayının başındaki 0 rakamlarını silmek. İlk capture group "-" veya boş string olabilir. Daha sonra bir veya daha fazla 0 gelebilir. Sonra negative lookahead ile 0'lardan sonra hemen string'in bitmediğini garanti ederiz. Tüm -000 şeklindeki karakterler - ile yer değiştirir. Tüm 000 şeklindeki karakterler "" yani boş string ile yer değiştirir.
"00000050.43".replaceFirst("^(-?)0+(?!$)", "$1")
Örnek
Şöyle yaparız. Bu / karakterine göre ayırır, ancak / karakterinin satır başında olmaması gerekir.
String[] res = "/token1/token2/token3".split("(?!^)/");
System.out.println(res[0]); // => /token1

Collectors groupingBy metodu - Classifier + Collector - Map Of X Haline Getirir

Giriş
Şu satırı dahil ederiz.
import static java.util.stream.Collectors.groupingBy;
Yani nesneyi kendi içindeki bir alana göre 
1. MultiMap (Map of List<X>) haline getirir veya
2. Map of Aggregate haline getirir.

groupingBy metodu - classifier yani keyMapper + downstream yani Collector
downstream map'in sağ tarafındaki nesnenin ne olacağını belirtir. Metodun imzası şöyledir.
groupingBy(classifier, downstream)
Metod bir Map döner.

-Map nesnesinin key alanı classifier'ın döndürdüğü tiptir
-Value alanı ise downstream'in döndürdüğü tiptir.

Classifier key değerini döner. Böylece nesneler key değerlerine göre gruplanır. Aynı key değerine sahip nesneleri downStream'e verilir.

Böylece istenirse
1 - One To One - örneğin Map<Key,Collectors.counting()
2. One To Many Map<Key,Set<X>
3. One To Many Map<Key,List<X>

şeklinde çıktılar alınabilir.

Örnek - Aggregate
Aynı departmanda çalışan kişi sayısı şöyle bulunur. Aggregate olarak her grubu sayan Collectors.counting() kullanılıyor
Map<Department, Long> map =
    list.stream()
    .collect(Collectors.groupingBy(Employee::getDep, Collectors.counting()));
Şöyle bir çıktı alabiliriz.
Personnel: 4
Accounting: 3 
Production: 3
Örnek - Aggregate
Şöyle yaparız. Aggregate olarak her grubun uzunluğunun ortalamasını alan Collectors.averagingDouble() kullanılıyor. Grupta uzunluğu 4,5,10 olan üç string varsa ortalama 19/3 olarak alınır.
// groupingBy and averagingDouble are static imports from
// java.util.stream.Collectors
Map<Character, Double> map = Arrays.stream(str.split(" "))
  .collect(groupingBy(word -> Character.toLowerCase(word.charAt(0)),
    averagingDouble(String::length)));
Örnek -One To Many (Set)
Elimizde şöyle bir kod olsun.
List<Pair<A,B>> list = //some list of pairs ; 
Şöyle yaparız.
Map<A,Set<Pair<A,B>> m =   list.stream().collect(Collectors.groupingBy((Pair::getLeft),
  Collectors.toSet()));
Örnek - One To Many (List)
Elimizde key=value listesi olsun. Key alanına göre gruplayarak Key=List<Value> haline getirmek isteyelim
A=groupA1
A=groupA2
A=groupA3
B=groupB1
B=groupB2
Şöyle yaparız
Map<String, List<String>> res = lines.stream()
  .map(s -> Arrays.asList(s.split("=")))
  .collect(Collectors.groupingBy(s -> s.get(0),
                                 Collectors.mapping(v->v.get(1),
                                 Collectors.toList())
));
Örnek - One To Many (List)
Elimizde şöyle bir kod olsun.
List<String> locations = Arrays.asList("US:5423","US:6321","CA:1326","AU:5631");
Bunu şöyle gruplamak isteyelim.
AU = [5631]
CA = [1326]
US = [5423, 6321]
Şöyle yaparız.
Map<String, List<String>> locationMap = locations.stream()
        .map(s -> s.split(":"))
        .collect(Collectors.groupingBy(a -> a[0],
                Collectors.mapping(a -> a[1], Collectors.toList())));
Örnek - One To Many (List)
Elimizde şöyle bir kod olsun
[0] : id = "34234", team = "gools", name = "bob", type = "old"
[1] : id = "23423", team = "fool" , name = "sam", type = "new"
[2] : id = "34342", team = "gools" , name = "dan", type = "new"
Veriyi şöyle multimap haline getirmek isteyelim
gools":
       ["id": 34234, "name": "bob", "type": "old"],
       ["id": 34342, "name": "dan", "type": "new"]

"fool":
       ["id": 23423, "name": "sam", "type": "new"]
Şöyle yaparız
Map<String, List<Pojo>> teamMap = 
    daoList.stream()
           .collect(Collectors.groupingBy(GenericDAO::getTeam,
                                          Collectors.mapping (dao -> new Pojo(...),
                                                              Collectors.toList())));
Diğer
Bu groupingBy overload hali aslında şu metod ile aynıdır. Bir Map yaratılır. classifier ile key nesnesi yaratılır. key map'te yok ise yeni ArrayList yaratılır. Varsa ArrayList'e eklenir.
Map<String, List<String>> res = lines.stream()
.map(s -> Arrays.asList(s.split("=")))
.collect(HashMap::new,
 (map, item) -> map.computeIfAbsent(item.get(0), k -> new ArrayList<>()).add(item.get(1)),
  HashMap::putAll);