Java 的 Tuple 元组数据类型

元组类型,即 Tuple 常在脚本语言中出现,例如 Scala 的 ("Unmi", "china@qq.com", "blahbla")。元组可认为是象数组一样的容器,它的目的是让你方便构造和引用,例如 Pair 可认为是一个只能存两个元素的元组,像是个 Map; 真正的元组应该是可以任意多个元素的容器,绕来绕去,它还是数组,或列表,所以我们实现上还是要借助于数组或是列表。

先看 Scala 中什么是元组:

val tuple = ("Unmi", "fantasia@sina.com", "blahblah...")
println(tuple._1)  //输出 Unmi

Scala 中访问从 1 开始,用 ._1 方式来访问其中的元素。

场景:当在一个方法中, 你需要返回几个对象,这几个对象的类型一致,你可以返回一个数组;如果几个对象的类型不同呢,当然你可以返回一个Object[]数组,可是这样在使用结果数组的时候,就需要强转对象的类型,会导致类型不安全;也可以定义一个dto,当多个场景下需要使用的不同,需要定义多个dto,这样会类爆炸,而且重用率极低;在非常接近Java语言的Scala里有元组的定义:val t = (1, 3.14, "Fred"),就是一个不同类型的数据放到一个线性集合里,在Java里我们可以模拟出一个类似的结构,以适合上面的场景。

示例一:

参照于此,写出一个 Java 版本的 Tuple,为增长你的键盘的使用寿命,我们把方法名也缩短了,例如 make 缩写为 mk,引用元素的方法名为 _,仍然保持 Java 的习惯,索引从 0 开始:

package com.sf.tuple;

/**
 * A simple java tuple
 */
public class Tuple<A> {

    /**
     * 静态方法
     * 
     * @param args
     * @return
     */
    public static <A> Tuple mk(A... args) {
        return new Tuple(args);
    }

    private A[] items;

    /**
     * 私有构造函数
     * 
     * @param items
     */
    private Tuple(A[] items) {
        this.items = items;
    }

    public A _(int index) {
        if (index < 0 || items == null || index > items.length - 1) {
            return null;
        }
        return items[index];
    }

    public static void main(String[] args) {
        Tuple<String> t = Tuple.mk("Unmi", "china@qq.com");
        System.out.println(t._(0)); // 输出 Unmi
        System.out.println(t._(1)); // 输出 china@qq.com
    }
}

结果:

Unmi
china@qq.com

代码间加了一个 main 测试方法,上面的代码输出什么无需多说了。

这样就实现了 Tuple.mk()  后接任意多个参数来构造一个 Tuple 对象。

示例二:

package com.sf;

import com.google.common.base.Optional;

abstract class Tuple {  
  
    public static void main (String[] args) {  
        Tuple tuple2 = Tuple.<String, Integer>of("hello", 1);  
        Tuple tuple3 = Tuple.<String, Integer, String>of("hello", 1, "hi");  
        System.out.println(tuple2._1().get() + "|" + tuple2._2().get());  
        System.out.println(tuple3._1().get() + "|" + tuple3._2().get() + "|" + tuple3._3().get());  
  
    }  
  
    public static  <E, T> Tuple of (E e, T t) {  
        return new Tuple2(e, t);  
    }  
  
    public static  <E, T, K> Tuple of (E e, T t, K k) {  
        return new Tuple3(e, t, k);  
    }  
  
    public abstract <E> Optional<E> _1 ();  
  
    public abstract <E> Optional<E> _2 ();  
  
    public abstract <E> Optional<E> _3 ();  
  
}  
  
class Tuple2<E, T> extends Tuple {  
    private E e;  
    private T t;  
  
    Tuple2 (E e, T t) {  
        this.e = e;  
        this.t = t;  
    }  
  
    @Override  
    public Optional<E> _1 () {  
        return Optional.of(e);  
    }  
  
    @Override  
    public Optional<T> _2 () {  
        return Optional.of(t);  
    }  
  
    @Override  
    public <E> Optional<E> _3() {  
        return Optional.absent();  
    }  
}  
  
class Tuple3<E, T, K> extends Tuple {  
    private E e;  
    private T t;  
    private K k;  
  
    Tuple3 (E e, T t, K k) {  
        this.e = e;  
        this.t = t;  
        this.k = k;  
    }  
  
    public Optional<E> _1 () {  
        return Optional.of(e);  
    }  
  
    public Optional<T> _2 () {  
        return Optional.of(t);  
    }  
  
    public Optional<K> _3 () {  
        return Optional.of(k);  
    }  
} 

结果:

hello|1
hello|1|hi

上面的代码中定义了三个类,父类为抽象类Tuple,此父类就是定义了一些模板方法,方法名有点不像Java方法名的命名规范,那是模仿scala里的方法命名,Tuple类没有其他作用,只是提供静态方法,创建Tuple的之类充当容器,提供多个容器的入口;

 Tuple2<E,T>可以充当两个对象的容器,该容器内保持两个对象的引用,通过方法_1(), _2()获取第一个和第二个对象的值,在此并没有直接返回对象,而是返回一个Optional对象,这是提醒使用返回值的方法做非Null检查;

 Tuple3<E,T,K>原理类似Tuple2,类似的可以做针对4个以及更多的对象容器,作为方法返回参数类型。

原文地址:https://www.cnblogs.com/duanxz/p/3645058.html