Java8 actual notes 0x06

How to missing values ​​modeling

class Person {
    private Car car;
    public Car getCar() {
        return car;
    }
}

class Car {
    private Insurance insurance;

    public Insurance getInsurance() {
        return insurance;
    }
}

class Insurance {
    private String name;

    public String getName() {
        return name;
    }
}

public class Main {
    public static String getCarInsuranceName(Person person) {
        return person.getCar().getInsurance().getName();
    }
}
  • In general, if Personnot Car, it getCar()is set to return null, indicating that the value is missing. Therefore necessary to determine whether the return value nullto preventNullPointerException

Reducing defensive checks using NullPointerException

  • Deep question: will increase the number of layers of code indentation, do not have the scalability, code maintenance difficult.
public static String getCarInsuranceName(Person person) {
        if (person != null) {
            Car car = person.getCar();
            if (car != null) {
                Insurance insurance = car.getInsurance();
                if (insurance != null) {
                    return insurance.getName();
                }
            }
        }
        return "Unknown";
    }
  • Excessive exit statement: the number of exit points and more difficult to maintain.
public static String getCarInsuranceName(Person person) {
        if (person == null) {
            return "Unknown";
        }
        Car car = person.getCar();
        if (car == null) {
            return "Unknown";
        }
        Insurance insurance = car.getInsurance();
        if (insurance == null) {
            return "Unknown";
        }
        return insurance.getName();
    }

problems caused by null

  • Error source: NullPointerExceptionis the Java development process in the most typical exception.
  • Code bloat: deep nested need nullto check, unreadable.
  • Meaningless: nullitself does not have any semantics, it is the wrong way to missing values modeling.
  • Violation of philosophy: Java has been trying to avoid the process of staff aware of the existence of the pointer, but nullthe pointer exceptions.
  • Type is missing: nulldo not belong to any type, which means it can be assigned to any variable, and when this variable is passed to the rest of the system will not be able to determine nullvariable is initially what type.

Other alternatives are null languages

  • Groovy: the introduction of safe navigation operator can safely access may be nullvariable, to avoid the throw NullPointerException.
def carInsuranceName = person?.car?.insurance?.name
  • Haskell: Maybetype, essentially optionalthe package value.
  • Scala: Option[T], to explicitly call avaliablethe operation to check whether the variable has a value, in fact, a disguised form of nullchecks.

Optional Class Profile

  • Variable exists, Optionalthe type of the object is simply packaged. When the variable does not exist, the missing value is modeled as a "empty" Optionalobjects, the method Optional.empty()returns. Optional.empty()The method is a static factory method, which returns Optionala specific single instance of the class.
class Person {
    private Car car;

    public Optional<Car> getCar() {
        return Optional.ofNullable(car);
    }
}

class Car {
    private Insurance insurance;

    public Optional<Insurance> getInsurance() {
        return Optional.ofNullable(insurance);
    }
}

class Insurance {
    private String name;

    public String getName() {
        return name;
    }
}
  • OptionalAnd nullimportant semantic difference is that Optionalkind clearly demonstrates allowed to happen variable is missing, nullis not allowed.In the code, if the variable is not null, then you do not need to add a nullcheck because nullchecks will only cover up the problem, not really fix the problem.
  • The above code portions corresponding to the book-shaped member when declaring such variables private Optional<Car> car, but this time a warning message IDEA 'Optional' used as field or parameter type, reference StackOverFlow , Optionalas a member variable or function argument types can result in unnecessary additional packaging and unpacking logic, and can not be serialized, Thus only used at the return value Optional.

Optional application of several models

Creating Optional objects

  • An empty statementOptional
Optional<Car> optCar = Optional.empty();
  • Optional created based on a non-null value
Optional<Car> optCar = Optional.of(car)大专栏  Java8实战笔记0x06ass="token punctuation">;
  • Acceptability nullof Optional, if passed nullthen get an empty object
Optional<Car> optCar = Optional.ofNullable(car);

Optional objects extracted from the map using the converted value and

Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);
  • If a Optionalcontains a value, this value is then passed to the function as a parameter map, the value will be converted. If Optionalempty, do nothing.

Optional use flatMap link objects

Optional<Person> optPerson = Optional.of(person);



  • Note at the above code will not compile. The first mapreturn value type Optional<Optional<Car>>, not required Optional<Car>.
  • Should be used to solve the above problems flatMap, flatMapthe method takes a function as an argument, a return value of this function is another stream. This method will be applied to each elementary stream, forming a new stream.

public static String getCarInsuranceName(Person person) {
        return Optional.ofNullable(person)
                .flatMap(Person::getCar)
                .flatMap(Car::getInsurance)
                .map(Insurance::getName)
                .orElse("Unknown");
    }

The default behavior of objects and dereference Optional

  • get(): If there is a variable return package variable values, otherwise throw an NoSuchElementExceptionexception. Not recommended.
  • orElse(T other): If the variable exists is returned, otherwise returns the passed default.
  • orElseGet(Supplier<? extends X> other): Is the orElse()delay calling edition. Incoming Supplieronly called when the variable does not exist. If the object is to create a time-consuming operation should use this method.
  • orElseThrow(Supplier<? extends x> exceptionSupplier): Similar get(), but errors are thrown by the incoming Suppliercreation.
  • ifPresent(Consumer<? extends T> consumer): When there is an execution variable passed Consumer, or not do anything.

Optional combination of two objects

public Optional<Insurance> safeFind(Person person, Car car) {
    return Optional.ofNullable(person)
            .flatMap(
                   p -> Optional.ofNullable(car).map(c -> find(p, c))
            );
}
  • First, c -> find(p, c)return Insurance, and the type of flow Optional, it is not necessary flatMap. After p -> Optional.ofNullable(car).map(c -> find(p, c))get is Optional<Insurance>, Optional.ofNullable(person)the stream type is Optional<Person>therefore required flatMap.

Use filter excluding certain value

  • filterThe method accepts as a parameter a predicate. If the Optionalvalue of the object exists, and it is consistent with the predicate conditions, filterthe method returns its value; otherwise it returns an empty Optionalobject.
public String getCarInsuranceName(Optional<Person> person, int minAge) {
    return person.filter(p -> p.getAge() >= minAge)
        .flatMap(Person::getCar)
        .flatMap(Car::getInsurance)
        .map(Insurance::getName)
        .orElse("Unknown");
}

Optional examples of actual use of the

Optional package with a value may be null

// 原始代码
Object value = map.get("key");
// if value != null ...

// 使用Optional
Optional<Object> value = Optional.ofNullable(map.get("key"));

Optional abnormal and contrast

// 将String转为Integer
public static Optional<Integer> stringToInt(String s) {
    try {
        return Optional.of(Integer.parseInt(s));
    } catch (NumberFormatExcption e) {
        return Optional.empty();
    }
}

// Java 9中添加了Stream.ofNullable,如果对象为null,则返回OptionalInt
public OptionalInt stringToInt(String s) {
    return Stream.ofNullable(s)
        .filter(str -> str.matches("\d+"))
        .mapToInt(Integer::parseInt)
        .findAny();
}

Guess you like

Origin www.cnblogs.com/liuzhongrong/p/12000174.html