Slide 1

Slide 1 text

@jeanneboyarsky 1 Java: Did You Know That? Jeanne Boyarsky Thursday February 20, 2020 DevNexus speakerdeck.com/boyarsky

Slide 2

Slide 2 text

@jeanneboyarsky About Me • Java Champion • Author • Developer at NYC bank for 17+ years • FIRST Robotics Mentor 2

Slide 3

Slide 3 text

@jeanneboyarsky Pause for a Commercial 3 Java 11 certs •1Z0-815 - Out now •1Z0-816 - April ETA

Slide 4

Slide 4 text

@jeanneboyarsky With Contributions By • Janeice DelVecchio • Elena Felder • Scott Selikoff 4

Slide 5

Slide 5 text

@jeanneboyarsky Removing in a Loop 5

Slide 6

Slide 6 text

@jeanneboyarsky Removing in a Loop 6 List list = new ArrayList<>(); list.add("red"); list.add("alliance"); list.add(“blue"); list.add("alliance"); for(String current : list) { list.remove(current); } System.out.println(list); Output: ConcurrentModificationException

Slide 7

Slide 7 text

@jeanneboyarsky Removing in a Loop 7 List list = new ArrayList<>(); list.add("red"); list.add("alliance"); for(String current : list) { list.remove(current); } System.out.println(list); Output: [alliance]

Slide 8

Slide 8 text

@jeanneboyarsky Behavior Explanation 8 1.List starts as [red, alliance] 2.First iteration through loop, current = red 3.In loop, remove red 4.Now list is [alliance] 5.For loop checks size. 6.Size = 1; already saw one element 7.Done!

Slide 9

Slide 9 text

@jeanneboyarsky Behavior Explanation 9 1.vs List as [red, alliance, blue, alliance] 2.Size = 3 after removal and saw one 3.Not Done! 4.Exception

Slide 10

Slide 10 text

@jeanneboyarsky Removing in a Loop 10 List list = new CopyOnWriteArrayList<>(); list.add("red"); list.add("alliance"); list.add("blue"); list.add("alliance"); for(String current : list) { list.remove(current); } System.out.println(list); Output: []

Slide 11

Slide 11 text

@jeanneboyarsky Or ditch the loop 11 list.clear(); (or) list.removeIf(x -> true); Output: []

Slide 12

Slide 12 text

@jeanneboyarsky Creating a Set 12

Slide 13

Slide 13 text

@jeanneboyarsky Creating a Set 13 String[] words = { "all", "the", “words", "in", "the", "world" }; Set set = new HashSet<>( Arrays.asList(words)); System.out.println(set); Output like: [all, the, world, in, words]

Slide 14

Slide 14 text

@jeanneboyarsky Creating a Set 14 String[] words = { "all", "the", “words", "in", "the", "world" }; Set set = Set.of(words); System.out.println(set); Output: IllegalArgumentException: duplicate element: the

Slide 15

Slide 15 text

@jeanneboyarsky Behavior Explanation 15 1.Set.of() takes varargs. 2.Doc says can’t have duplicates

Slide 16

Slide 16 text

@jeanneboyarsky Backed Collection 16

Slide 17

Slide 17 text

@jeanneboyarsky Collection 17 Map map = new HashMap<>(); map.put("Braves", "Atlanta"); map.put("Mets", "NYC"); Set keys = new HashSet<>(map.keySet()); keys.remove("Mets"); System.out.println(map); {Mets=NYC, Braves=Atlanta}

Slide 18

Slide 18 text

@jeanneboyarsky Collection 18 Map map = new HashMap<>(); map.put("Braves", "Atlanta"); map.put("Mets", "NYC"); Set keys = map.keySet(); keys.remove("Mets"); System.out.println(map); {Braves=Atlanta}

Slide 19

Slide 19 text

@jeanneboyarsky Behavior Explanation 19 1.keySet(), values(), and entrySet() are backed collections 2.When change any, it affects original map

Slide 20

Slide 20 text

@jeanneboyarsky Overloading 20

Slide 21

Slide 21 text

@jeanneboyarsky Overloading 21 public void check(Number number) { System.out.print(“Number "); } public void check(Integer integer) { System.out.print(“Integer "); } public void delegator(Number number) { check(number); } Integer num = Integer.valueOf(42); Overloading target = new Overloading(); target.check(num); target.delegator(num); Output: Integer Number

Slide 22

Slide 22 text

@jeanneboyarsky Overloading 22 public void check(Number number) { System.out.print(“Number "); } public void check(Integer integer) { System.out.print(“Integer "); } public void delegator(Number number) { check(number); } Number num = Integer.valueOf(42); Overloading target = new Overloading(); target.check(num); target.delegator(num); Output: Number Number

Slide 23

Slide 23 text

@jeanneboyarsky Behavior Explanation 23 1.Method chosen at compile time, not runtime. 2.(vs polymorphism on objects)

Slide 24

Slide 24 text

@jeanneboyarsky == 24

Slide 25

Slide 25 text

@jeanneboyarsky Equality 25 Integer int1 = Integer.valueOf(8); Integer int2 = Integer.valueOf(8); System.out.println((int1 == int2) + " " + int1.equals(int2)); true true

Slide 26

Slide 26 text

@jeanneboyarsky Equality 26 Integer int1 = Integer.valueOf(8_000); Integer int2 = Integer.valueOf(8_000); System.out.println((int1 == int2) + " " + int1.equals(int2)); false true

Slide 27

Slide 27 text

@jeanneboyarsky Behavior Explanation 27 1.Wrapper classes cache small values 2.Lesson: always use equals() for objects

Slide 28

Slide 28 text

@jeanneboyarsky var and inference 28

Slide 29

Slide 29 text

@jeanneboyarsky var and inference 29 List x1 = List.of(); List x2 = List.of(1, 2, 3); Stream.of(x1, x2) .flatMap(x -> x.stream()) .map(x -> x + 1) .forEach(System.out::print); Output: 234

Slide 30

Slide 30 text

@jeanneboyarsky var and inference 30 List x1 = List.of(); var x2 = List.of(1, 2, 3); Stream.of(x1, x2) .flatMap(x -> x.stream()) .map(x -> x + 1) .forEach(System.out::print); Output: 234

Slide 31

Slide 31 text

@jeanneboyarsky var and inference 31 var x1 = List.of(); var x2 = List.of(1, 2, 3); Stream.of(x1, x2) .flatMap(x -> x.stream()) .map(x -> x + 1) .forEach(System.out::print); Compiler error: Operator ‘+’ cannot be applied to capture, int

Slide 32

Slide 32 text

@jeanneboyarsky Behavior Explanation 32 1.var x2 = List.of(1,2,3) 2.x2 is a List 3.var x1 = List.of() 4.x1 is a not a List 5.Stream.of(x1, x2) is a Stream> 6.flatMap makes Stream 7.Object doesn’t go with +

Slide 33

Slide 33 text

@jeanneboyarsky Sorting Characters 33

Slide 34

Slide 34 text

@jeanneboyarsky Sorting Characters 34 Stream ohMy = Stream.of( "lions", "tigers", "bears"); Comparator c = Comparator.naturalOrder(); System.out.println(ohMy.collect( Collectors.groupingBy(String::length, Collectors.mapping(s -> s.charAt(0), Collectors.minBy(c))))); Output: {5=Optional[b], 6=Optional[t]}

Slide 35

Slide 35 text

@jeanneboyarsky Sorting Characters 35 Stream ohMy = Stream.of( "lions", "tigers", "bears"); System.out.println(ohMy.collect( Collectors.groupingBy(String::length, Collectors.mapping(s -> s.charAt(0), Collectors.minBy( Comparator.naturalOrder()))))); Compiler error No suitable method found for….

Slide 36

Slide 36 text

@jeanneboyarsky The actual message 36 Error:(18, 51) java: no suitable method found for groupingBy(String::length,java.util.stream.Collector>) method java.util.stream.Collectors.groupingBy(java.util.function. Function) is not applicable (cannot infer type-variable(s) T,K (actual and formal argument lists differ in length)) method java.util.stream.Collectors.groupingBy(java.util.func tion.Function,java.util.stream.Collector) is not applicable (inference variable U has incompatible upper bounds java.lang.Object,java.lang.Comparable,T,T)…

Slide 37

Slide 37 text

@jeanneboyarsky The other message 37 Error:(19, 52) java: cannot find symbol symbol: method charAt(int) location: variable s of type java.lang.Object

Slide 38

Slide 38 text

@jeanneboyarsky Behavior Explanation 38 1.char != Character
 Inferred type check fails 2.Propagates error to other call 3.But, this suggests a workaround…

Slide 39

Slide 39 text

@jeanneboyarsky Sorting Characters 39 Stream ohMy = Stream.of( "lions", "tigers", "bears"); System.out.println(ohMy.collect( Collectors.groupingBy(String::length, Collectors.mapping((String s) -> s.charAt(0), Collectors.minBy( Comparator.naturalOrder()))))); Output: {5=Optional[b], 6=Optional[t]}

Slide 40

Slide 40 text

@jeanneboyarsky URL Equality 40

Slide 41

Slide 41 text

@jeanneboyarsky URL Equality 41 URL url1 = new URL("https://google.com"); URL url2 = new URL("https://google.com"); System.out.println(url1.equals(url2)); Output: true

Slide 42

Slide 42 text

@jeanneboyarsky URL Equality 42 URL url1 = new URL("cloudURL"); URL url2 = new URL(“cloudURL"); System.out.println(url1.equals(url2)); Output: false if DNS resolution changes during program

Slide 43

Slide 43 text

@jeanneboyarsky Behavior Explanation 43 1.URL’s equals method calls the URLStreamHandler’s equals method 2.Which uses DNS resolution 3.Cloud URLs change often Instead, use URI https://news.ycombinator.com/ item?id=21765788

Slide 44

Slide 44 text

@jeanneboyarsky Week of the Year 44

Slide 45

Slide 45 text

@jeanneboyarsky Week of Year 45 LocalDate xmasEve = LocalDate.of( 2019, Month.DECEMBER, 24); WeekFields weekFields = WeekFields.of( Locale.getDefault()); int weekNumber = xmasEve.get( weekFields.weekOfWeekBasedYear()); int week = xmasEve.get( weekFields.weekOfYear()); System.out.println(weekNumber + " " + week); Output: 52 52

Slide 46

Slide 46 text

@jeanneboyarsky Week of Year 46 LocalDate newYearsEve = LocalDate.of( 2019, Month.DECEMBER, 31); WeekFields weekFields = WeekFields.of( Locale.getDefault()); int weekNumber = newYearsEve.get( weekFields.weekOfWeekBasedYear()); int week = newYearsEve.get( weekFields.weekOfYear()); System.out.println(weekNumber + " " + week); Output: 1 53

Slide 47

Slide 47 text

@jeanneboyarsky Behavior Explanation 47 1.Most years are 52 weeks + 1 day 2.2020 started on a Wednesday. 3.The week based week starts the Sunday before 4.Whereas weekOfYear() returns 1-54

Slide 48

Slide 48 text

@jeanneboyarsky Week of Year 48 LocalDate xmasEve = LocalDate.of( 2019, Month.DECEMBER, 24); DateTimeFormatter format = DateTimeFormatter.ofPattern( "yyyy-MM-dd"); DateTimeFormatter format2 = DateTimeFormatter.ofPattern( "YYYY-MM-dd"); System.out.println(xmasEve.format(format) + " " + xmasEve.format(format2)); Output: 2019-12-24 2019-12-24

Slide 49

Slide 49 text

@jeanneboyarsky Week of Year 49 LocalDate newYearsEve = LocalDate.of( 2019, Month.DECEMBER, 31); DateTimeFormatter format = DateTimeFormatter.ofPattern( "yyyy-MM-dd"); DateTimeFormatter format2 = DateTimeFormatter.ofPattern( "YYYY-MM-dd"); System.out.println( newYearsEve.format(format) + " " + newYearsEve.format(format2)); Output: 2019-12-31 2020-12-31

Slide 50

Slide 50 text

@jeanneboyarsky Behavior Explanation 50 1.y is year 2.Y is week of year 3.Be careful with week of year!

Slide 51

Slide 51 text

@jeanneboyarsky Closing Resources 51

Slide 52

Slide 52 text

@jeanneboyarsky JDBC 52 PreparedStatement stmt = conn.prepareStatement( "update mytable set updated = now()"); try (stmt) { stmt.executeUpdate(); } “Good”

Slide 53

Slide 53 text

@jeanneboyarsky JDBC 53 PreparedStatement stmt = conn.prepareStatement( "update mytable set updated = now()" + " where key = ?"); stmt.setString(1, "abc"); try (stmt) { stmt.executeUpdate(); } Resource leak!

Slide 54

Slide 54 text

@jeanneboyarsky Behavior Explanation 54 1.What happens if an exception is thrown while calling the PreparedStatement setter? 2.The try-with-resources doesn’t run 3.Resource leak!

Slide 55

Slide 55 text

@jeanneboyarsky JDBC 55 PreparedStatement stmt = conn.prepareStatement( "update mytable set updated = now()" + " where key = ?"); try (stmt) { stmt.setString(1, "abc"); stmt.executeUpdate(); } “good”

Slide 56

Slide 56 text

@jeanneboyarsky IO 56 try (BufferedReader reader = Files.newBufferedReader(path)) { String line = null; while ((line = reader.readLine())!= null) { // process line } } No leak

Slide 57

Slide 57 text

@jeanneboyarsky IO 57 Files.lines(path).count(); Resource leak!

Slide 58

Slide 58 text

@jeanneboyarsky Behavior Explanation 58 1.Resource not closed by terminal operation 2.Affects 1.find() 2.lines() 3.list() 4.newDirectoryStream() 5.walk()

Slide 59

Slide 59 text

@jeanneboyarsky IO 59 try (Stream stream = Files.lines(path)) { stream.count(); } Good

Slide 60

Slide 60 text

@jeanneboyarsky PSA: Free Tools •PMD •FindBugs •CheckStyle •SonarQube - examples: •No return in finally •Close resources •All sorts of bugs 60

Slide 61

Slide 61 text

@jeanneboyarsky Other Favorites? ??? 61