java8根据某个id删选_Java 8可选
java8根據某個id刪選
在編程時,我們都面臨著(最) 臭名昭著的NullPointerException 。 而且我相信我們所有人都同意,遇到NullPointerException也是一種痛苦。 為了使讀者了解最新情況,著名的計算機科學家Tony Hoare引入了空引用,他認為這是一個百萬美元的錯誤 。 眾所周知,這很容易實現,但是也很難預測。 這就是為什么開發人員需要非常謹慎的原因。
平常的方式
讓我們考慮以下3個簡單的POJO。
public class Employee {private Car car;public Car getCar() {return car;} }public class Car {private Insurance insurance;public Insurance getInsurance() {return insurance;} }public class Insurance {private String name;public String getName() {return name;} }僅提供背景信息–員工可以擁有汽車(雖然不是強制性的),汽車可以具有保險(不一定),并且保險必須始終具有名稱。 只要記住了解以下內容即可。
現在,我們想通過提供人員實例來獲得保險的名稱。
public String getInsuranceName(Employee employee) {if (employee != null) {Car car = employee.getCar();if (car != null) {Insurance insurance = car.getInsurance();if (insurance != null) {return insurance.getName();}}}return "UNKNOWN"; }這是我們通常采取的預防措施,以免遇到可怕的NullPointerException異常。 我們還認為這也會污染源代碼,根據我的觀點,應將其視為反模式。
另一種慣用的方式
上一節中提到的對null檢查的這種深層嵌套看起來有些晦澀。 有時人們會以不同的方式來做。
public String getInsuranceName(Employee employee) {if (employee == null) {return "UNKNOWN";}Car car = employee.getCar();if (car == null) {return "UNKNOWN";}Insurance insurance = car.getInsurance();if (insurance == null) {return "UNKNOWN";}return insurance.getName(); }在我看來,這還算不錯,因為它不包含深層嵌套的null檢查。 但是它仍然遵循相同的反模式,以某種不同的方式檢查空值。
為什么NULL不好?
NULL的替代
很少有語言,例如Scala,Groovy消除了對空引用的可怕使用,以表示沒有值。 可以以非常簡潔的方式用Groovy編寫類似的代碼。
def name = employee?.car?.insurance?.name? 這在Groovy中被稱為“ 安全導航”運算符 ,它清楚地顯示了易讀的代碼,同時消除了遇到可怕的空引用的可能性。
Java的努力
現在我們應該問,Java開發人員可以做什么來實現類似的事情,從而在保持可讀性和可維護性源代碼的同時,防止NullPointerException的可能性。 Java語言設計人員選擇了Groovy或Scala語言已經實現的類似方法,但是引入了一個新類-Optional
可選的
public final class Optional<T> {public static<T> Optional<T> empty() {}public static <T> Optional<T> of(T value) {}public static <T> Optional<T> ofNullable(T value) {}public T get() {}public boolean isPresent() {}public void ifPresent(Consumer<? super T> consumer) {}public Optional<T> filter(Predicate<? super T> predicate) {}public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {}public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {}public T orElse(T other) {}public T orElseGet(Supplier<? extends T> other) {}public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {} }此類主要用于表示值的不存在。 如果您認為一個值可以始終存在或不能始終存在,則最好使用Optional類型。 在我們之前的示例中,員工可能會或可能不會有汽車,這就是為什么最好返回Optional <Car>而不是簡單地返回Car 。
讓我們看看我們如何設計上一個示例:
public class Employee {private Car car;public Optional<Car> getCar() {return Optional.ofNullable(car);} }public class Car {private Insurance insurance;public Optional<Insurance> getInsurance() {return Optional.ofNullable(insurance);} }public class Insurance {private String name;public String getName() {return name;} }我沒有討論過靜態工廠的Nullable(..)方法,而只是將其視為包裝值的包裝實用程序方法,而不管其引用如何。
只需查看API,就可以輕松了解遇到可選類型時需要執行的操作。 對于開發人員而言,遇到此類可選類型總是表示缺少值的可能性,因此開發人員可以為此采取適當的措施。
可選創作
從類概述中,我們可以清楚地看到可以以多種方式創建Optional 。
可選的提取和轉換
到目前為止,我們已經看到了如何創建Optional實例。 現在我們應該看看如何提取值或將其轉換為另一個值。
但是我們應該如何使用呢?
Car car = employee.getCar(); if (employee != null) {car = employee.getCar(); }這是我們逃避NullPointerException的主要操作。 現在,使用Java 8 Optional ,我們可以編寫如下代碼:
Optional<Car> car = employee.getCar(); if (!car.isEmpty()) {Car car = car.get(); }但是,您是否認為這是對討厭的空檢查的改進?
我曾經認為它是一種改進,因為它隱藏了空指針,但是后來,我覺得它會污染源代碼。 但是我不反對使用從方法或包裝變量中返回Optional作為類型的方法。 我將在以下各節中討論其背后的原因。
讓我們考慮以前的方法:
public String getInsuranceName(Employee employee) {return employee.getCar().getInsurance().getName(); }這是一個非常干凈的代碼,但是NullPointerException潛伏在后面,這就是為什么我們需要合并幾個空引用檢查(我們之前已經看到過)的原因。
如果我們在設計一個好的API時合并了公共String Optional ,則可以通過更簡潔的方式實現:
public String getInsuranceName(Optional<Employee> employee) {return employee.flatMap(Employee::getCar).flatMap(Car::getInsurance).map(Insurance::getName).orElse("UNKNOWN"); }這是不是真的好又干凈的方法? 我知道這會使一些對Java Streams API不滿意的程序員感到困惑。 我強烈建議對Java 8 Streams有一個快速的了解,以了解Optional的優點。
另一個示例是如果人名以“ P”開頭,則獲得保險名稱
public String getInsuranceName(Optional<Employee> employee) {return employee.filter(e-> e.getName().startsWith("P")).flatMap(Employee::getCar).flatMap(Car::getInsurance).map(Insurance::getName).orElse("UNKNOWN"); }設計實踐
現在,我想以一些不同的方式分享一些有關設計我們先前討論的POJO的想法。
API設計實踐1
public class Employee {private Optional<Car> car;public Optional<Car> getCar() {return car;} }public class Car {private Optional<Insurance> insurance;public Insurance getInsurance() {return insurance;} }public class Insurance {private String name;public String getName() {return name;} }在這里,我已聲明成員變量為Optional類型。 根據我的觀點,這也是非常用戶友好的,并且此類的用戶或消費者可以輕松理解此類的性質。 在這種情況下,員工的汽車是Optional的 ,也就是說,員工可能也可能沒有汽車。
API設計實踐2
public class Employee {private Car car;public Optional<Car> getCar() {return Optional.ofNullable(car);} }public class Car {private Insurance insurance;public Optional<Insurance> getInsurance() {return Optional.ofNullable(insurance);} }public class Insurance {private String name;public String getName() {return name;} }這也是非常直觀的,但是缺乏清晰顯示成員實例不存在的想法。 要了解任何系統,開發人員總是需要首先了解對象模型,而了解對象模型則需要我們了解領域對象。 在這種情況下,員工是擁有汽車的域對象,就像它對于員工是強制性的一樣。 但實際上,員工可能會或可能不會有汽車。 我們可以在獲取或檢索其值( getCar() )時實現它,然后當該方法返回Optional時 ,我們可能會注意到其缺少包含值的可能性。
使用什么?
它完全取決于開發人員。 我個人更喜歡第一種方法,因為很明顯在理解領域模型方面很明顯,而第二種方法在序列化方面具有優勢。 由于Optional不實現Serializable ,因此在我們的第一種方法中它不可序列化。 如果我們使用DTO,則可以使我們的實現適應第二種方法。
方法或構造函數參數中的可選
正如我之前提到的,“ 可選”在班級中清楚地表明了消費者應該做的事情。 因此,如果構造函數或方法接受Optional元素作為參數,則意味著該參數不是必需的。
另一方面,我們需要付出用Optional污染代碼庫的代價。 開發人員唯一要謹慎使用它。 我個人不希望在方法參數中使用Optional ,但如果需要,我們仍然可以將其包裝在Optional實例中并對其執行必要的操作。
方法返回類型中的可選
Java語言架構師Brian Goetz還建議,如果有可能返回null,則在方法中返回Optional 。 我們已經在API設計規范2中看到了這一點。
從方法拋出異?;蚍祷乜蛇x
多年來,Java開發人員遵循通常的方法拋出異常來表示方法調用中的錯誤情況。
public static InputStream getInputStream(final String path) {checkNotNull(path, "Path cannot be null");final URL url = fileSystem.getEntry(path);InputStream xmlStream;try {xmlStream = url.openStream();return xmlStream;} catch (final IOException ex) {throw new RuntimeException(ex);} }如果此方法的使用者遇到RuntimeException ,那是由于打開與指定URL的連接時出現問題。 另一方面,我們還可以通過以下方式使用Optional :
public static Optional<InputStream> getInputStream(final String path) {checkNotNull(path, "Path cannot be null");final URL url = fileSystem.getEntry(path);InputStream xmlStream;try {xmlStream = url.openStream();return Optional.of(xmlStream);} catch (final IOException ex) {return Optional.empty();} }我認為這很直觀,因為它清楚地表明它返回了一個可能有值也可能沒有值的Optional實例。 這就是為什么我傾向于從可能具有這種null遇到可能性的方法中返回Optional的原因。
私有方法中的可選返回類型
私有方法顯然不是要理解或分析項目的任何重要部分。 因此,我認為我們仍然可以使用null檢查來擺脫過多的Optional,但是如果您認為仍然可以以更簡潔明了的方式使用該方法,則也可以返回Optional 。
為了更好地理解,我編寫了一個示例,如下所示:
private void process(final String data) {try {final ItemList nList = doc.getChildNodes();for (int temp = 0; temp < nList.getLength(); temp++) {final Node nNode = nList.item(temp);final String key = nNode.getName();final String value = nNode.getValue();values.put(getAttribute(key).orElseThrow(IllegalArgumentException::new), value);}} catch (final Exception ex) {logger.error("{}", ex.getMessage(), ex);} }private Optional<Attribute> getAttribute(final String key) {return Arrays.stream(Attribute.values()).filter(x -> x.value().filter(y -> y.equalsIgnoreCase(key)).isPresent()).findFirst(); }public static enum Attribute {A ("Sample1"),B ("Sample2"),C ("Sample3");private String value;private Attribute(String value) {this.value = value;}public Optional<String> value() {return Optional.ofNullable(value);}}我本可以以更常用的方式編寫第二種方法:
private Attribute getAttribute(final String key) {for (final Attribute attribute : Attribute.values()) {Optional<String> value = attribute.value();if (value.isPresent() && value.get().equalsIgnoreCase(key)) {return attribute;}}throw new IllegalArgumentException(); }私有方法中返回返回Collection或其任何子類型的可選返回類型
作為第一個示例,請考慮代碼,您需要實現一種方法來從Java中的指定路徑列出文件
public static List<String> listFiles(String file) {List<String> files;try {files = Files.list(Paths.get(path));} catch (IOException e) {files = Arrays.asList("Could not list");}return files; }我們可以實現更簡潔的代碼,如下所示:
public static List<String> listFiles(String path) {return Files.list(Paths.get(path)).filter(Files::isRegularFile).collect(toList()); }注意,簡潔方法中的返回類型仍為List而不是Optional 。 最好遵循返回空列表的通常做法,而不是使用Optional 。
使用Optional的流方式更加簡潔是非常有專利的。 可選的是實用程序數據容器,可幫助開發人員擺脫空引用。 此外,它確實提供了許多有用的方法來簡化程序員的任務。 但是,如果開發人員不太了解Optional的主要用法,則Optional可能會被嚴重濫用,并可能污染代碼庫。 這就是為什么我強烈建議大家在Optional中使用面向流的方法,以幫助開發人員編寫簡潔且可維護的代碼
翻譯自: https://www.javacodegeeks.com/2017/07/java-8-optionals.html
java8根據某個id刪選
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java8根据某个id删选_Java 8可选的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: zip unzip_zip和unzip上
- 下一篇: 最大的病毒用什么电脑语言(最简单的电脑病