-
Notifications
You must be signed in to change notification settings - Fork 0
/
java-basics-optionals.html
207 lines (185 loc) · 52 KB
/
java-basics-optionals.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<!DOCTYPE html><html lang="de-ch"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Java basics: Optionals - Finecloud</title><meta name="description" content="What are Optionals? For the the number one use case for them has to do with null values. So whenever we're dealing with objects in Java, we store references to objects in variables. And those variables may or may not actually be pointing back to…"><meta name="generator" content="Publii Open-Source CMS for Static Site"><link rel="stylesheet" href="https://www.finecloud.ch/media/plugins/syntaxHighlighter/prism-black.css"><link rel="canonical" href="https://www.finecloud.ch/java-basics-optionals.html"><link rel="alternate" type="application/atom+xml" href="https://www.finecloud.ch/feed.xml"><link rel="alternate" type="application/json" href="https://www.finecloud.ch/feed.json"><meta property="og:title" content="Java basics: Optionals"><meta property="og:site_name" content="Finecloud"><meta property="og:description" content="What are Optionals? For the the number one use case for them has to do with null values. So whenever we're dealing with objects in Java, we store references to objects in variables. And those variables may or may not actually be pointing back to…"><meta property="og:url" content="https://www.finecloud.ch/java-basics-optionals.html"><meta property="og:type" content="article"><link rel="shortcut icon" href="https://www.finecloud.ch/media/website/finecloud.png" type="image/png"><link rel="stylesheet" href="https://www.finecloud.ch/assets/css/style.css?v=39da73365516a098a9b73b721fc970e2"><script type="application/ld+json">{"@context":"http://schema.org","@type":"Article","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.finecloud.ch/java-basics-optionals.html"},"headline":"Java basics: Optionals","datePublished":"2022-08-29T06:48","dateModified":"2022-08-30T06:00","description":"What are Optionals? For the the number one use case for them has to do with null values. So whenever we're dealing with objects in Java, we store references to objects in variables. And those variables may or may not actually be pointing back to…","author":{"@type":"Person","name":"Finecloud","url":"https://www.finecloud.ch/authors/finecloud/"},"publisher":{"@type":"Organization","name":"Finecloud"}}</script><meta name="google-site-verification" content="seFY9U12uiEq5U3_MyZiX6XWzk0AVFl9zITr2ZKsytY"></head><body><div class="site-container"><header class="top" id="js-header"><a class="logo" href="https://www.finecloud.ch/">Finecloud</a><nav class="navbar js-navbar"><button class="navbar__toggle js-toggle" aria-label="Menu" aria-haspopup="true" aria-expanded="false"><span class="navbar__toggle-box"><span class="navbar__toggle-inner">Menu</span></span></button><ul class="navbar__menu"><li><a href="https://www.finecloud.ch/" target="_self">Blog</a></li><li><a href="https://www.finecloud.ch/tags/" target="_self">Tags</a></li></ul></nav><div class="search"><div class="search__overlay js-search-overlay"><div class="search__overlay-inner"><form action="https://www.finecloud.ch/search.html" class="search__form"><input class="search__input js-search-input" type="search" name="q" placeholder="search..." aria-label="search..." autofocus="autofocus"></form><button class="search__close js-search-close" aria-label="Close">Close</button></div></div><button class="search__btn js-search-btn" aria-label="Search"><svg role="presentation" focusable="false"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#search"/></svg></button></div></header><main><article class="post"><div class="hero"><figure class="hero__image hero__image--overlay"><img src="https://www.finecloud.ch/media/website/download.jpg" srcset="https://www.finecloud.ch/media/website/responsive/download-xs.jpg 300w, https://www.finecloud.ch/media/website/responsive/download-sm.jpg 480w, https://www.finecloud.ch/media/website/responsive/download-md.jpg 768w, https://www.finecloud.ch/media/website/responsive/download-lg.jpg 1024w, https://www.finecloud.ch/media/website/responsive/download-xl.jpg 1360w, https://www.finecloud.ch/media/website/responsive/download-2xl.jpg 1600w" sizes="100vw" loading="eager" alt=""></figure><header class="hero__content"><div class="wrapper"><div class="post__meta"><time datetime="2022-08-29T06:48">August 29, 2022</time></div><h1>Java basics: Optionals</h1></div></header></div><div class="wrapper post__entry"><div class="post__toc"><h3>Table of Contents</h3><ul><li><a href="#mcetoc_1gb6umu2h1v">What are Optionals?</a><ul><li><a href="#mcetoc_1gb6umu2h20">Example Szenario</a></li></ul></li><li><a href="#mcetoc_1gb706fnv3r">of vs ofNullable</a></li><li><a href="#mcetoc_1gb7366m97v">get</a></li><li><a href="#mcetoc_1gb7366m980">orElseThrow</a></li><li><a href="#mcetoc_1gb9laqot5j">orElseGet</a></li><li><a href="#mcetoc_1gb9laqot5k">filter</a></li><li><a href="#mcetoc_1gbenn3osa4">Map Function on Optionals</a></li><li><a href="#mcetoc_1gbenn3osa5">Optionals in APIs and domain models</a></li><li><a href="#mcetoc_1gbmefukg4">Returning Optionals instead of throwing Exceptions</a></li><li><a href="#mcetoc_1gbmefukg5">List of Optionals</a></li></ul></div><h2 id="mcetoc_1gb6umu2h1v">What are Optionals?</h2><p>For the the number one use case for them has to do with null values. So whenever we're dealing with objects in Java, we store references to objects in variables. And those variables may or may not actually be pointing back to an object. For example, we could create a string called message and put a word in it. So in this case, the variable <em>message</em> is pointing to the object, which exist somewhere in memory. But we could also have, <em>message2 p</em>ointing to nothing. And if I try to do something like to call to upper, and if I run this, that's going to blow up with a null pointer exception. Because I'm trying to reference a method of a a method of an object that really does not exist.<br><br>And we don't like these null pointer exceptions because they cause our programs to stop, and we usually don't want our programs to blow up if we can help it.<br><br>Optionals let us wrap these variables in a little pretty box, and they provide us with some cool methods that can help us to detect whether or not we actually have any value in the box. And if we do, then we can proceed to do things with that value.</p><h3 id="mcetoc_1gb6umu2h20">Example Szenario</h3><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest</span> </span>{
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
Optional<String> optMsg = Optional.of(<span class="hljs-string" style="color: #6a8759;">"Hello"</span>);
System.out.println(optMsg);
}
}</pre><p>output:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">Optional[Hello]
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">0</span></pre><p>As you can see, it does print out the word hello, but it's surrounded by this optional thing because the object that we have here is not a string. It is an optional of a string.</p><h2 id="mcetoc_1gb706fnv3r"><em>of </em>vs <em>ofNullable</em></h2><p>Optional present themselves with this word optional and then brackets and then whatever thing is inside of it. And then it's calling the two string method of whatever object is inside of the optional. Note that optionals are really just wrappers for other objects or for nothing at all.</p><p>Here we've got the msg to uppercase, right? Let's say that we wrap this message in an optional. In this particular case, I have to create an optional of the msg to object using the <em>ofNullable </em>Method, because we can see that msg2 is <em>null. </em>Now I can provide an alternative string if that value was actually <em>null</em>. </p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest</span> </span>{
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
String msg = <span class="hljs-string" style="color: #6a8759;">"Hello"</span>;
String msg2 = <span class="hljs-keyword" style="color: #cc7832;">null</span>;
Optional<String> optMsg = Optional.ofNullable(msg2);
String finalOutput = optMsg.orElse(<span class="hljs-string" style="color: #6a8759;">"alternative"</span>).toUpperCase();
System.out.println(finalOutput);
}
}</pre><p>output:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">ALTERNATIVE
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">0</span></pre><p>So the point of all of this is that it should now be impossible to get a null pointer exception as a result of <em>msg2</em> value being <em>null</em> because of the <em>Optional.ofNullable()</em><br><br>So what about the <em>Optional.of()</em> ? Let's run this code:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest</span> </span>{
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
String msg = <span class="hljs-string" style="color: #6a8759;">"Hello"</span>;
String msg2 = <span class="hljs-keyword" style="color: #cc7832;">null</span>;
Optional<String> optMsg = Optional.of(msg2);
System.out.println(optMsg);
}
}</pre><p>output:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">Exception in thread <span class="hljs-string" style="color: #6a8759;">"main"</span> java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:<span class="hljs-number" style="color: #6897bb;">208</span>)
at java.base/java.util.Optional.of(Optional.java:<span class="hljs-number" style="color: #6897bb;">113</span>)
at section11_loose_ends.datastore.OptionalTest.main(OptionalTest.java:<span class="hljs-number" style="color: #6897bb;">10</span>)
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">1</span></pre><p>The reason for that is that this <em>of</em> method is expecting that the value you're passing in to it is not null. So you could use an <em>Optional.of</em> so that you could intentionally test and make sure that the values that you were passing in to it were not null.</p><p>You should generally only be using <em>Optional.of</em> in two cases:</p><ol><li>First case is you're 100% certain that the values that you will be passing into it won't be null.</li><li>You're not sure if the values might be <em>null</em> and you're ok with your program blowing up with a null pointer exception. Maybe in some cases you want that to happen, because the variables that shall be passing into the <em>Optional.of </em>99.9% of the time should not be null. And if they are, then you've got bigger problems and you want to know about those problems, right? We don't want our program to just carry on happily when unexpected circumstances occur. In some cases, we want the program to blow up and die with a nice stack trace so that we can learn.</li></ol><h2 id="mcetoc_1gb7366m97v"><em>get</em></h2><p>Let's run this and see what happens:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest</span> </span>{
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
String msg = <span class="hljs-string" style="color: #6a8759;">"Hello"</span>;
String msg2 = <span class="hljs-keyword" style="color: #cc7832;">null</span>;
Optional<String> optMsg = Optional.ofNullable(msg2);
System.out.println(optMsg.get());
}
}</pre><p>output:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">Exception in thread <span class="hljs-string" style="color: #6a8759;">"main"</span> java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:<span class="hljs-number" style="color: #6897bb;">143</span>)
at section11_loose_ends.datastore.OptionalTest.main(OptionalTest.java:<span class="hljs-number" style="color: #6897bb;">11</span>)
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">1</span></pre><p>So because we're using the <em>ofNullable</em>, we're not blowing up online ten anymore. When we pass in this <em>null</em> value now, we're blowing up with this <em>get(). </em>It just tries to get the value out. And it doesn't do any checks and it doesn't give us any options. And in that case, to do what we're doing here is really no better than just not using Optionals at all and just having a value that could possibly be null and then trying to use it right? So no advantage to that.</p><h2 id="mcetoc_1gb7366m980"><em>orElseThrow</em></h2><p>Let's say that we wanted to throw a different type of exception. This works like a supplier function. The thing that I'm going to return, though, will be something that extends runtime exception:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest</span> </span>{
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
String msg = <span class="hljs-string" style="color: #6a8759;">"Hello"</span>;
String msg2 = <span class="hljs-keyword" style="color: #cc7832;">null</span>;
Optional<String> optMsg = Optional.ofNullable(msg2);
System.out.println(optMsg.orElseThrow(() -> <span class="hljs-keyword" style="color: #cc7832;">new</span> RuntimeException(<span class="hljs-string" style="color: #6a8759;">"Whoops, Nothing found... "</span>)));
}
}</pre><p>output:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">Exception in thread <span class="hljs-string" style="color: #6a8759;">"main"</span> java.lang.RuntimeException: Whoops, Nothing found...
at section11_loose_ends.datastore.OptionalTest.lambda$main$<span class="hljs-number" style="color: #6897bb;">0</span>(OptionalTest.java:<span class="hljs-number" style="color: #6897bb;">11</span>)
at java.base/java.util.Optional.orElseThrow(Optional.java:<span class="hljs-number" style="color: #6897bb;">403</span>)
at section11_loose_ends.datastore.OptionalTest.main(OptionalTest.java:<span class="hljs-number" style="color: #6897bb;">11</span>)
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">1</span></pre><p>We can call its constructor so that we can pass in some simple message like nothing found. Typically in real life, you don't want to be creating new runtime exceptions like this. You want a first go look through all of the standard exceptions that are already created with Java and see if there's one that's already existing whose name matches with your circumstance. So like if you were looking for a file and you couldn't find one, maybe there's a runtime exception that has something to do with file related exceptions.<br><br>And only after you've looked through all of the standard exceptions and couldn't find one that matches with your circumstance in terms of its name, then you could consider creating your own class that extends runtime exception or exception if that's your case for, like a checked exception or something.</p><h2 id="mcetoc_1gb9laqot5j"><em>orElseGet</em></h2><p>This Method takes a supplier, which is one of the functional interfaces. It's an interface that represents a method are a function that doesn't take an input, but it supplies things or values.<br><br>We could have a method reference, like maybe there's some method somewhere else in our code that generates passwords. What you could have is something like basically, if they supplied the password, then go ahead and do whatever you were planning to do with the password. But if they did not supply the password, then maybe you're doing this <em>orElseGet</em> and then this <em>orElseGet</em> is pointing at a method reference to some fancy method that can generate new passwords for us each time we call it.</p><h2 id="mcetoc_1gb9laqot5k"><em>filter</em></h2><p>This filter here works pretty much exactly like the filter in the streams API takes a predicate does the same stuff, except where the filter from the Streams API would return a stream again.</p><p>A stream of whatever this filter here returns an optional of whatever. Lets look at this Example:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest_v2</span> </span>{
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
String msg = <span class="hljs-string" style="color: #6a8759;">"cat"</span>;
Optional<String> optMsg = Optional.ofNullable(msg);
System.out.println(optMsg.filter(s -> s.length() > <span class="hljs-number" style="color: #6897bb;">3</span>).orElse(<span class="hljs-string" style="color: #6a8759;">"invalid"</span>));
}
}</pre><p>output:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">invalid
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">0</span></pre><p>The functionality allows you to use this if you wanted to ensure not only that there should be an object inside of the optional, but you can also have a chance to test that object for some type of property or behavior or whatever. Now, if we want to make sure that we get something more legit to print, which would be some type of a string, we can fall back on our familiar fallback methods like orElse, so we can do an <em>orElse</em> and then say something like "invalid", right?<br><br>Now let's test what happens, though, if we actually put legitimate strings in here and not only one with the length of three:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest_v2</span> </span>{
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
String msg = <span class="hljs-string" style="color: #6a8759;">"cats"</span>;
Optional<String> optMsg = Optional.ofNullable(msg);
System.out.println(optMsg.filter(s -> s.length() > <span class="hljs-number" style="color: #6897bb;">3</span>).orElse(<span class="hljs-string" style="color: #6a8759;">"invalid"</span>));
}
}</pre><p>output:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;">cats
Process finished with exit code <span class="hljs-number" style="color: #6897bb;">0</span></pre><h2 id="mcetoc_1gbenn3osa4">Map Function on Optionals</h2><p>What if we have some custom Class or Records of which we want to access specific fields and use Optionals this for? Let's say we have an optional of a person class and we want to obtain just the first name, for example, of this person. Obviously, you can't just call a getfirstName Method on this Object, because this isn't a person that we're working with right, Ii's an optional. So I would have to first peel off the optional layer to get to the person underneath so that I can then get to the first name.<br><br>So I could do a <em>get</em>, which we already know is generally not a good idea or I could do and <em>orElse</em> right. However, now the <em>orElse</em> is wanting me to specify an alternative object that it should return if there wasn't anything in the optional. And that might be a little annoying in this case, because the alternative object isn't the string anymore, it's actually a person. I'd have to supply a whole other person as a backup person and that feels a little awkward. We don't really want to have to do all of that right?</p><p>But there's another thing that we could do: there's a map function on optionals, just like from the Streams API. We can use the map function to basically convert or translate whatever our main starring object type was within the stream to something else. So we could go from a stream of strings to a stream of integers or longs or something like that.</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest_v3</span> </span>{
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Car</span><span class="hljs-params">(String make, String model, String color, Year year)</span> </span>{}
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(String firstName, String lastName, Car car)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
Person p1 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Tom"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, <span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"X"</span>, <span class="hljs-string" style="color: #6a8759;">"Red"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2018</span>)));
Person p2 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Jerry"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, <span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"Y"</span>, <span class="hljs-string" style="color: #6a8759;">"White"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2020</span>)));
Optional<Person> optPerson = Optional.of(p1);
System.out.println(optPerson.map(person -> person.firstName)); <span class="hljs-comment" style="color: grey;">// traditional lambda expression</span>
System.out.println(optPerson.map(Person::firstName)); <span class="hljs-comment" style="color: grey;">// using a method reference</span>
}
}</pre><p>output:</p><p><code>Optional[Tom]</code><br><code>Optional[Tom]</code><br><br><code>Process finished with exit code 0</code></p><p>So we still have an Optional which does not allow Nullable Values. Let's further improve this:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest_v3</span> </span>{
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Car</span><span class="hljs-params">(String make, String model, String color, Year year)</span> </span>{}
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(String firstName, String lastName, Car car)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
Person p1 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Tom"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, <span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"X"</span>, <span class="hljs-string" style="color: #6a8759;">"Red"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2018</span>)));
Person p2 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Jerry"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, <span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"Y"</span>, <span class="hljs-string" style="color: #6a8759;">"White"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2020</span>)));
Person p3 = <span class="hljs-keyword" style="color: #cc7832;">null</span>;
Optional<Person> optPerson = Optional.ofNullable(p2);
<span class="hljs-comment" style="color: grey;">// System.out.println(optPerson.map(person -> person.firstName)); // traditional lambda expression</span>
System.out.println(optPerson
.map(Person::car)
.map(Car::make)
.orElse(<span class="hljs-string" style="color: #6a8759;">"Unknown firstName"</span>));
}
}</pre><p>output:</p><p><code>Tesla</code><br><br><code>Process finished with exit code 0</code></p><h2 id="mcetoc_1gbenn3osa5">Optionals in APIs and domain models</h2><p>Let's say that you're modeling a person like in the last example and you say, a person will always have to have a <em>firstName</em> and <em>lastName</em>, but they may optionally own a <em>Car</em>. Not everybody owns a car, especially people who live in cities. So owning a car could be considered optional. So you might want to model your <em>Person</em> class with that concept baked right in.</p><p>If we go ahead and just make the <em>Car</em> field optional, this leads to the problem that we will get a map inside of a map in our Lambda expression with the method reference of <code>.map(Car::make)</code></p><p>We can solve this my using a flatMap:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest_v3</span> </span>{
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Car</span><span class="hljs-params">(String make, String model, String color, Year year)</span> </span>{}
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(String firstName, String lastName, Optional<Car> car)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
Person p1 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Tom"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, Optional.of(<span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"X"</span>, <span class="hljs-string" style="color: #6a8759;">"Red"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2018</span>))));
Person p2 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Jerry"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, Optional.of(<span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"Y"</span>, <span class="hljs-string" style="color: #6a8759;">"White"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2020</span>))));
Person p3 = <span class="hljs-keyword" style="color: #cc7832;">null</span>;
Optional<Person> optPerson = Optional.ofNullable(p2);
<span class="hljs-comment" style="color: grey;">// System.out.println(optPerson.map(person -> person.firstName)); // traditional lambda expression</span>
System.out.println(optPerson
.flatMap(Person::car)
.map(Car::make)
.orElse(<span class="hljs-string" style="color: #6a8759;">"Unknown firstName"</span>));
}
}</pre><p>output:</p><p><code>Tesla</code><br><br><code>Process finished with exit code 0</code></p><h2 id="mcetoc_1gbmefukg4">Returning Optionals instead of throwing Exceptions</h2><p>A lot of newer APIs that do things like we did before may opt not to throw an exception anymore, but instead to model the API such that it would just return an optional. Lets improve our <em>Repository</em> Class to store People in it and access them by ID.</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric_v4</span><<span class="hljs-title" style="color: #ffc66d;">T</span> <span class="hljs-keyword" style="color: #cc7832;">extends</span> <span class="hljs-title" style="color: #ffc66d;">RepositoryGeneric_v4</span>.<span class="hljs-title" style="color: #ffc66d;">IDable</span><<span class="hljs-title" style="color: #ffc66d;">V</span>>, <span class="hljs-title" style="color: #ffc66d;">V</span>> </span>{
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(String fristName, String lastName, Long id)</span> implements IDable<Long></span>{};
<span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">interface</span> <span class="hljs-title" style="color: #ffc66d;">IDable</span><<span class="hljs-title" style="color: #ffc66d;">U</span>> </span>{
<span class="hljs-function">U <span class="hljs-title" style="color: #ffc66d;">id</span><span class="hljs-params">()</span></span>;
}
<span class="hljs-keyword" style="color: #cc7832;">private</span> List<T> records = <span class="hljs-keyword" style="color: #cc7832;">new</span> ArrayList<>();
<span class="hljs-function">List<T> <span class="hljs-title" style="color: #ffc66d;">findAll</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records;
}
<span class="hljs-function">T <span class="hljs-title" style="color: #ffc66d;">save</span><span class="hljs-params">(T record)</span> </span>{
records.add(record);
<span class="hljs-keyword" style="color: #cc7832;">return</span> record;
}
<span class="hljs-keyword" style="color: #cc7832;">static</span> <T,V> <span class="hljs-function">V <span class="hljs-title" style="color: #ffc66d;">encrypt</span><span class="hljs-params">(T data, Function<T, V> func)</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> func.apply(data);
}
<span class="hljs-function">Optional<T> <span class="hljs-title" style="color: #ffc66d;">findById</span><span class="hljs-params">(<span class="hljs-keyword" style="color: #cc7832;">long</span> id)</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> records.stream().filter(p -> p.id().equals(id)).findFirst();
}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
RepositoryGeneric_v4<Person, Long> pRepo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric_v4<>();
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Chuck"</span>, <span class="hljs-string" style="color: #6a8759;">"Norris"</span>, <span class="hljs-number" style="color: #6897bb;">10L</span>));
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Max"</span>, <span class="hljs-string" style="color: #6a8759;">"Müller"</span>, <span class="hljs-number" style="color: #6897bb;">20L</span>));
pRepo.save(<span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-string" style="color: #6a8759;">"Hans"</span>, <span class="hljs-string" style="color: #6a8759;">"Wurst"</span>, <span class="hljs-number" style="color: #6897bb;">30L</span>));
Person foundPerson = pRepo.findById(<span class="hljs-number" style="color: #6897bb;">30L</span>).get();
System.out.println(foundPerson);
<span class="hljs-comment" style="color: grey;">// System.out.println(pRepo.findAll());</span>
System.out.println(RepositoryGeneric_v4.<String, String>encrypt(<span class="hljs-string" style="color: #6a8759;">"Hello"</span>, m -> m.toUpperCase()));
System.out.println(RepositoryGeneric_v4.<String, Integer>encrypt(<span class="hljs-string" style="color: #6a8759;">"Test"</span>, m -> m.hashCode()));
}
}</pre><p>output:</p><p><code>Jerry</code><br><br><code>Process finished with exit code 0</code></p><p>What if we now have the Case of an inexistent findById call:</p><p><code> String fName = repo.findById(300L)</code></p><p>will return:</p><p><code>firstName not found</code><br><br><code>Process finished with exit code 0</code></p><p>Isn't that nice? We don't have to deal with an exception where we'd have to use a try catch block and then try it in and then catch it and then do some alternative business because we didn't get the thing that we were looking for the record that we were looking for right now.<br><br>Instead, we can just use the same code for both circumstances of whether or not we found the actual person from the data store from the repository. This is much more concise code than even having to do the try catch block and all of that business and most Java developers don't really care for doing a whole lot of try catch blocks because it just kind of looks nasty.</p><h2 id="mcetoc_1gbmefukg5">List of Optionals</h2><p>See how you can filter out null Values in a List of Optionals Stream:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest_v5</span> </span>{
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Car</span><span class="hljs-params">(String make, String model, String color, Year year)</span> </span>{}
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(Long id, String firstName, String lastName, Optional<Car> car)</span> implements RepositoryGeneric_v4.IDable<Long>, RepositoryGeneric_v4.Saveable </span>{}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
RepositoryGeneric_v4<Person, Long> repo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric_v4<>();
Person p1 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-number" style="color: #6897bb;">100L</span>, <span class="hljs-string" style="color: #6a8759;">"Tom"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, Optional.of(<span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"X"</span>, <span class="hljs-string" style="color: #6a8759;">"Red"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2018</span>))));
Person p2 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-number" style="color: #6897bb;">200L</span>, <span class="hljs-string" style="color: #6a8759;">"Jerry"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, Optional.of(<span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"Y"</span>, <span class="hljs-string" style="color: #6a8759;">"White"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2020</span>))));
Person p3 = <span class="hljs-keyword" style="color: #cc7832;">null</span>;
Person p4 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-number" style="color: #6897bb;">400L</span>, <span class="hljs-string" style="color: #6a8759;">"Jake"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, Optional.of(<span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"3"</span>, <span class="hljs-string" style="color: #6a8759;">"Blue"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2019</span>))));
Person p5 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-number" style="color: #6897bb;">500L</span>, <span class="hljs-string" style="color: #6a8759;">"Johnny"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, Optional.of(<span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"S"</span>, <span class="hljs-string" style="color: #6a8759;">"Black"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2021</span>))));
List<Optional<Person>> people = List.of(Optional.of(p1), Optional.of(p2), Optional.ofNullable(p3), Optional.of(p4), Optional.of(p5));
people.stream()
.filter(Optional::isPresent) <span class="hljs-comment" style="color: grey;">// filter out the null's</span>
.map(Optional::get) <span class="hljs-comment" style="color: grey;">// unwrap the Optionals to the actual Objects</span>
.map(Person::firstName)
.forEach(System.out::println);
}
}</pre><p>output:</p><p><code>Tom</code><br><code>Jerry</code><br><code>Jake</code><br><code>Johnny</code><br><br><code>Process finished with exit code 0</code><br><br>but you can also use the Stream API directly on an Object, like so:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">OptionalTest_v5</span> </span>{
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Car</span><span class="hljs-params">(String make, String model, String color, Year year)</span> </span>{}
<span class="hljs-function">record <span class="hljs-title" style="color: #ffc66d;">Person</span><span class="hljs-params">(Long id, String firstName, String lastName, Optional<Car> car)</span> implements RepositoryGeneric_v4.IDable<Long>, RepositoryGeneric_v4.Saveable </span>{}
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-keyword" style="color: #cc7832;">static</span> <span class="hljs-keyword" style="color: #cc7832;">void</span> <span class="hljs-title" style="color: #ffc66d;">main</span><span class="hljs-params">(String[] args)</span> </span>{
RepositoryGeneric_v4<Person, Long> repo = <span class="hljs-keyword" style="color: #cc7832;">new</span> RepositoryGeneric_v4<>();
Person p1 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-number" style="color: #6897bb;">100L</span>, <span class="hljs-string" style="color: #6a8759;">"Tom"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, Optional.of(<span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"X"</span>, <span class="hljs-string" style="color: #6a8759;">"Red"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2018</span>))));
Person p2 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-number" style="color: #6897bb;">200L</span>, <span class="hljs-string" style="color: #6a8759;">"Jerry"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, Optional.of(<span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"Y"</span>, <span class="hljs-string" style="color: #6a8759;">"White"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2020</span>))));
Person p3 = <span class="hljs-keyword" style="color: #cc7832;">null</span>;
Person p4 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-number" style="color: #6897bb;">200L</span>, <span class="hljs-string" style="color: #6a8759;">"Jake"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, Optional.of(<span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"3"</span>, <span class="hljs-string" style="color: #6a8759;">"Blue"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2019</span>))));
Person p5 = <span class="hljs-keyword" style="color: #cc7832;">new</span> Person(<span class="hljs-number" style="color: #6897bb;">200L</span>, <span class="hljs-string" style="color: #6a8759;">"Johnny"</span>, <span class="hljs-string" style="color: #6a8759;">"Thumb"</span>, Optional.of(<span class="hljs-keyword" style="color: #cc7832;">new</span> Car(<span class="hljs-string" style="color: #6a8759;">"Tesla"</span>, <span class="hljs-string" style="color: #6a8759;">"S"</span>, <span class="hljs-string" style="color: #6a8759;">"Black"</span>, Year.of(<span class="hljs-number" style="color: #6897bb;">2021</span>))));
Optional<Person> p11 = Optional.ofNullable(p1);
p11.stream()
.map(Person::firstName)
.forEach(System.out::println);
<span class="hljs-comment" style="color: grey;">//</span>
<span class="hljs-comment" style="color: grey;">// List<Optional<Person>> people = List.of(Optional.of(p1), Optional.of(p2), Optional.ofNullable(p3), Optional.of(p4), Optional.of(p5));</span>
<span class="hljs-comment" style="color: grey;">// people.stream()</span>
<span class="hljs-comment" style="color: grey;">// .filter(Optional::isPresent) // filter out the null's</span>
<span class="hljs-comment" style="color: grey;">// .map(Optional::get) // unwrap the Optionals to the actual Objects</span>
<span class="hljs-comment" style="color: grey;">// .map(Person::firstName)</span>
<span class="hljs-comment" style="color: grey;">// .forEach(System.out::println);</span>
}
}</pre><p>output: </p><p><code>Tom</code><br><br><code>Process finished with exit code 0</code></p></div><footer class="wrapper post__footer"><p class="post__last-updated">This article was updated on August 30, 2022</p><ul class="post__tag"><li><a href="https://www.finecloud.ch/tags/java/">java</a></li><li><a href="https://www.finecloud.ch/tags/java-basics/">java basics</a></li><li><a href="https://www.finecloud.ch/tags/lambda/">lambda</a></li><li><a href="https://www.finecloud.ch/tags/softwareentwicklung/">software development</a></li><li><a href="https://www.finecloud.ch/tags/stream-api/">stream-api</a></li></ul><div class="post__share"></div></footer></article><nav class="post__nav"><div class="post__nav-inner"><div class="post__nav-prev"><svg width="1.041em" height="0.416em" aria-hidden="true"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#arrow-prev"/></svg> <a href="https://www.finecloud.ch/java-basics-generics.html" class="post__nav-link" rel="prev"><span>Previous</span> Java basics: Generics</a></div><div class="post__nav-next"><a href="https://www.finecloud.ch/java-basics-dates-and-time.html" class="post__nav-link" rel="next"><span>Next</span> Java basics: Dates and Time </a><svg width="1.041em" height="0.416em" aria-hidden="true"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#arrow-next"/></svg></div></div></nav><div class="post__related related"><div class="wrapper"><h2 class="h5 related__title">You should also read:</h2><article class="related__item"><div class="feed__meta"><time datetime="2022-05-26T14:07" class="feed__date">Mai 26, 2022</time></div><h3 class="h1"><a href="https://www.finecloud.ch/java-collection-iteratoren.html">Java Collection Iteratoren</a></h3></article><article class="related__item"><div class="feed__meta"><time datetime="2022-05-26T13:28" class="feed__date">Mai 26, 2022</time></div><h3 class="h1"><a href="https://www.finecloud.ch/java-collection-sets.html">Java Collection Sets</a></h3></article><article class="related__item"><div class="feed__meta"><time datetime="2022-05-26T13:19" class="feed__date">Mai 26, 2022</time></div><h3 class="h1"><a href="https://www.finecloud.ch/java-collection-listen.html">Java Collection Listen</a></h3></article></div></div></main><footer class="footer"><div class="footer__copyright"><p>Powered by Publii</p></div><button onclick="backToTopFunction()" id="backToTop" class="footer__bttop" aria-label="Back to top" title="Back to top"><svg><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#toparrow"/></svg></button></footer></div><script>window.publiiThemeMenuConfig = {
mobileMenuMode: 'sidebar',
animationSpeed: 300,
submenuWidth: 'auto',
doubleClickTime: 500,
mobileMenuExpandableSubmenus: true,
relatedContainerForOverlayMenuSelector: '.top',
};</script><script defer="defer" src="https://www.finecloud.ch/assets/js/scripts.min.js?v=6ca8b60e6534a3888de1205e82df8528"></script><script>var images = document.querySelectorAll('img[loading]');
for (var i = 0; i < images.length; i++) {
if (images[i].complete) {
images[i].classList.add('is-loaded');
} else {
images[i].addEventListener('load', function () {
this.classList.add('is-loaded');
}, false);
}
}</script><script defer="defer" src="https://www.finecloud.ch/media/plugins/syntaxHighlighter/prism.js"></script></body></html>