Repository: apache/dubbo
File: dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RadixTree.java (Java)

Code before:
    }

    public RadixTree(boolean caseSensitive) {
        this(caseSensitive, '/');
    }

    public RadixTree(char separator) {
        this(true, separator);
    }

    public RadixTree() {
        this(true, '/');
    }

    /**
     * This is a default implementation that does not check for equality.
     */
    public T addPath(PathExpression path, T value) {
        return addPath(path, value, (t, t2) -> Boolean.TRUE);
    }

    /**
     * When equalFunction is not null, if a node is found at the path, it will not be returned immediately; <br/>
     * instead, whether to return it depends on the result of the function.
     */
    public T addPath(PathExpression path, T value, BiFunction<T, T, Boolean> equalFunction) {
        if (path.isDirect()) {
            KeyString key = new KeyString(path.getPath(), caseSensitive);
            List<Match<T>> matches = directPathMap.computeIfAbsent(key, k -> new ArrayList<>());
            for (int i = 0, size = matches.size(); i < size; i++) {
                Match<T> match = matches.get(i);
                if (match.getValue().equals(value)) {
                    return match.getValue();
                }
            }
            matches.add(new Match<>(path, value));
            return null;
        }

        Node<T> current = root;
        PathSegment[] segments = path.getSegments();
        for (int i = 0, len = segments.length; i < len; i++) {
            Node<T> child = getChild(current, segments[i]);
            if (i == len - 1) {
                List<Pair<PathExpression, T>> values = child.values;
                for (Pair<PathExpression, T> pathExpressionTPair : values) {
                    if (pathExpressionTPair.getLeft().equals(path)) {
                        T rightVal = pathExpressionTPair.getRight();
                        if (equalFunction == null) {
                            return rightVal;
                        } else {

Review comment (suggestion):
Support null is not a good design, as users may not understand its meaning. It is recommended to use `Objects#requireNonNull(T)` for null checks instead.

Code after:
        this.separator = separator;
    }

    public RadixTree(boolean caseSensitive) {
        this(caseSensitive, '/');
    }

    public RadixTree(char separator) {
        this(true, separator);
    }

    public RadixTree() {
        this(true, '/');
    }

    /**
     * This is a default implementation that does not check for equality.
     */
    public T addPath(PathExpression path, T value) {
        return addPath(path, value, (t, t2) -> Boolean.TRUE);
    }

    /**
     * When the path is the same, the predicate is used to determine whether the values are considered equal.
     * If the predicate returns true, the existing value is returned directly.
     */
    public T addPath(PathExpression path, T value, BiFunction<T, T, Boolean> predicate) {
        Objects.requireNonNull(predicate);
        if (path.isDirect()) {
            KeyString key = new KeyString(path.getPath(), caseSensitive);
            List<Match<T>> matches = directPathMap.computeIfAbsent(key, k -> new ArrayList<>());
            for (int i = 0, size = matches.size(); i < size; i++) {
                Match<T> match = matches.get(i);
                if (predicate.apply(match.getValue(), value)) {
                    return match.getValue();
                }
            }
            matches.add(new Match<>(path, value));
            return null;
        }

        Node<T> current = root;
        PathSegment[] segments = path.getSegments();
        for (int i = 0, len = segments.length; i < len; i++) {
            Node<T> child = getChild(current, segments[i]);
            if (i == len - 1) {
                List<Pair<PathExpression, T>> values = child.values;
                for (int j = 0, size = values.size(); j < size; j++) {
                    if (values.get(j).getLeft().equals(path)) {
                        if (predicate.apply(values.get(j).getRight(), value)) {
                            return values.get(j).getRight();