场景

当我们调用某个方法,需要有超过一个值的返回时,我们通常会怎么做,比如现在需要调用方法返回姓名和年龄两个属性(假如姓名为张三,年龄为12)。

  • 方式一:使用Map,将Map中分别放入name为key,张三为value;age为key,12为value。

    • 缺点是需要定义key值,且书写语法比较繁琐。

    • 优点是定义明确。

  • 方式二:直接定义一个Person对象,定义name和age两个属性。

    • 缺点是比较繁琐,这个Person对象可能整个项目中只被使用这一次。

    • 优点是定义非常明确,不容易产生歧义。

新的方法

当我们方法调用返回值大于一个属性,且就仅有这一次调用,不存在复用和共用问题时,可以采用如下方式:

package objectDemo;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.ImmutableTriple;

public class Demo {

    public static void main(String[] args) {
        ImmutablePair<String, Integer> person = ImmutablePair.of("张三", 12);
        System.out.println(person);
        // 三个元素
        ImmutableTriple<String, Integer, String> personInfo = ImmutableTriple.of("李四", 20, "上海");
        System.out.println(personInfo);
    }
}
(张三,12)
(李四,20,上海)

Pair抽象类详解


而common-lang包提供了组件的方式来返回多个参数,Pair接口,返回一对数据Pair抽象类,它集成了Map.Entry接口。

Pair是一个抽象类,这个类是定义基本API的抽象实现,它指的是左右两个元素,它也实现了Map.Entry接口(即Map中的元素),也就是key是左元素,value是右元素;类似于python中的tuple。

子类实现的是可能是可变的也可能是不可变的,然而对存储的对象类型是没有限制的,如果可变的对象存储在Pair中,那么Pair对象也会变为可变的;

抽象类的源码如下:

package org.apache.commons.lang3.tuple;
import java.io.Serializable;
import java.util.Map;
import java.util.Objects;

import org.apache.commons.lang3.builder.CompareToBuilder;
/**
* 抽象类实现Map.Entry接口  
*/
public abstract class Pair<L, R> implements Map.Entry<L, R>, Comparable<Pair<L, R>>, Serializable {

    private static final long serialVersionUID = 4954918890077093841L;
  /**
   * 返回一个不可变的ImmutablePair对象,即:左元素不可变、右元素不可变,Map的值也不可变
   */
    public static <L, R> Pair<L, R> of(final L left, final R right) {
        return new ImmutablePair<>(left, right);
    }
   /**
   * 获取左元素
   */
    public abstract L getLeft();
   /**
   * 获取右元素
   */
    public abstract R getRight();
   /**
   * 从Map中获取key
   */
    @Override
    public final L getKey() {
        return getLeft();
    }
   /**
   * 获取Map中value
   */
    @Override
    public R getValue() {
        return getRight();
    }
   /**
   * 比较基于左元素和右元素的配对
   */
    @Override
    public int compareTo(final Pair<L, R> other) {
      return new CompareToBuilder().append(getLeft(), other.getLeft())
              .append(getRight(), other.getRight()).toComparison();
    }
  /**
   * 比较两个Pair对应的值是否相等,基于左右两个元素
   */
    @Override
    public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj instanceof Map.Entry<?, ?>) {
            final Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj;
            return Objects.equals(getKey(), other.getKey())
                    && Objects.equals(getValue(), other.getValue());
        }
        return false;
    }
   /**
   * 返回合适的哈希代码
   */
    @Override
    public int hashCode() {
        // see Map.Entry API specification
        return (getKey() == null ? 0 : getKey().hashCode()) ^
                (getValue() == null ? 0 : getValue().hashCode());
    }

  /**
   * 返回Pair的左右元素的字符串比奥斯
   */
    @Override
    public String toString() {
        return "(" + getLeft() + ',' + getRight() + ')';
    }

  /**
   * 格式化字符串
   */
    public String toString(final String format) {
        return String.format(format, getLeft(), getRight());
    }

}

ImmutablePair不可变的左右元素对

package org.apache.commons.lang3.tuple;

public final class ImmutablePair<L, R> extends Pair<L, R> {
    /**
     * 返回不可变的Pair对象,左右元素都为null
     */
    @SuppressWarnings("rawtypes")
    private static final ImmutablePair NULL = ImmutablePair.of(null, null);

    private static final long serialVersionUID = 4954918890077093841L;
    /**
     * 静态方法,返回元素对为null的不可变Pair对象
     */
    @SuppressWarnings("unchecked")
    public static <L, R> ImmutablePair<L, R> nullPair() {
        return NULL;
    }

    /**
     * 返回Pair的左元素
     */
    public final L left;
    /**
     * 返回Pair的右元素
     */
    public final R right;
    /**
     * 返回不可变Pair元素对对象
     */
    public static <L, R> ImmutablePair<L, R> of(final L left, final R right) {
        return new ImmutablePair<>(left, right);
    }

    /**
     * 构造函数,传递左元素、右元素
     */
    public ImmutablePair(final L left, final R right) {
        super();
        this.left = left;
        this.right = right;
    }

    /**
     * 获取左元素
     */
    @Override
    public L getLeft() {
        return left;
    }

    /**
     * 获取右元素
     */
    @Override
    public R getRight() {
        return right;
    }
    /**
     * 设置元素,但是会报异常
     */
    @Override
    public R setValue(final R value) {
        throw new UnsupportedOperationException();
    }

}

MutablePair可以改变的左右元素对