【Java数据结构与算法】第二十一章 元组

本文介绍了Java中元组的概念,元组用于存储不同类型的数据,允许多态性。文章展示了如何自定义二元组和三元组,并提供了一个元组工具类用于方便地创建和操作元组。此外,还提到了第三方库javatuples,提供了从数组和集合创建元组的方法。示例代码演示了如何使用元组存储实体类信息,展示了其灵活性。
摘要由CSDN通过智能技术生成

【Java数据结构与算法】第二十一章 元组

1.概念

元组(Tuple)是一种数据结构,可以存放多个元素,每个元素的数据类型可以不同。用List与Tuple类比,List只能存储一种数据类型,而Tuple可以存储多种数据类型

元组也是关系型数据库中的基本概念,表中的每行,或者说表中的每条记录,就是一个元组,每行的每列都可以是不同的数据类型

元组将一组对象直接打包存储为单一对象,这个对象只允许读取,不允许存放新的对象

2.自定义元组

二元组

public class TwoTuple<A, B>{
	public final A first;
	public final B second;
	
	public TwoTuple(A a, B b){
		this.first = a;
		this.second = b;
	}
}

三元组

public class ThreeTuple<A, B, C> extends TwoTuple<A, B>{
	public final C third;

	public ThreeTuple(A a, B b, C c){
		super(a, b);
		this.third = c;
	}	
}

元组操作工具类、测试类

/*
 * 元组辅助类:用于多种类型值的返回,如在分页的时候,后台存储过程既返回了查询得到的当页
 * 的数据(List类型),又得到了数据表中数据总数(Integer类型)
 * 使用泛型方法实现,利用参数类型推断,编译器可以找出具体的类型
 * 
public class TupleUtil{
	public static <A, B> TwoTuple<A, B> tuple(A a, B b){
		return new TwoTuple<A, B>(a, b);
	}

	public static <A, B, C> ThreeTuple<A, B. C> tuple(A a, B b, C c){
		return new ThreeTuple<A, B, C>(a, b, c);
	}

	//测试
	public static void main(String[] args){
		List<GoodsBean> goodsBeans = new ArrayList<GoodBean>();
		for(int i = 1; i < 26; i++){
			GoodsBean goodsBean = new GoodsBean();
			goodsBean.setGoodsId(i);
			goodsBeans.add(goodsBean);
		}
		Integer totalProperty = 47;
		TwoTuple<List<GoodsBean>, Integer> twoTuple = TupleUtil.tuple(goodsBeans, totalProperty);
		List<GoodsBean> list = twoTuple.first;
		Integer count = twoTuple.second;
	}
}

3.第三方Jar包

Maven坐标

<dependency>
	<groupId>org.javatuples</groupId>
	<artifactId>javatuples</artifactId>
	<version>1.2</version>
</dependency>

Jar包中的类主要是Tuple基础类、一元组、二元组…十元组,以及键值对元组
在这里插入图片描述
IValue3

package org.javatuples.valueintf;

public interface IValue3<X> {

    public X getValue3();
    
}

Triplet

package org.javatuples;

import java.util.Collection;
import java.util.Iterator;

import org.javatuples.valueintf.IValue0;
import org.javatuples.valueintf.IValue1;
import org.javatuples.valueintf.IValue2;

/**
 * <p>
 * A tuple of three elements.
 * </p> 
 * 
 * @since 1.0
 * 
 * @author Daniel Fern&aacute;ndez
 *
 */
public final class Triplet<A,B,C> 
        extends Tuple
        implements IValue0<A>,
                   IValue1<B>,
                   IValue2<C> {

    private static final long serialVersionUID = -1877265551599483740L;

    private static final int SIZE = 3;

    private final A val0;
    private final B val1;
    private final C val2;

    public static <A,B,C> Triplet<A,B,C> with(final A value0, final B value1, final C value2) {
        return new Triplet<A,B,C>(value0,value1,value2);
    }

    /**
     * <p>
     * Create tuple from array. Array has to have exactly three elements.
     * </p>
     * 
     * @param <X> the array component type 
     * @param array the array to be converted to a tuple
     * @return the tuple
     */
    public static <X> Triplet<X,X,X> fromArray(final X[] array) {
        if (array == null) {
            throw new IllegalArgumentException("Array cannot be null");
        }
        if (array.length != 3) {
            throw new IllegalArgumentException("Array must have exactly 3 elements in order to create a Triplet. Size is " + array.length);
        }
        return new Triplet<X,X,X>(array[0],array[1],array[2]);
    }

    /**
     * <p>
     * Create tuple from collection. Collection has to have exactly three elements.
     * </p>
     * 
     * @param <X> the collection component type 
     * @param collection the collection to be converted to a tuple
     * @return the tuple
     */
    public static <X> Triplet<X,X,X> fromCollection(final Collection<X> collection) {
        return fromIterable(collection);
    }

    /**
     * <p>
     * Create tuple from iterable. Iterable has to have exactly three elements.
     * </p>
     * 
     * @param <X> the iterable component type 
     * @param iterable the iterable to be converted to a tuple
     * @return the tuple
     */
    public static <X> Triplet<X,X,X> fromIterable(final Iterable<X> iterable) {
        return fromIterable(iterable, 0, true);
    }

    /**
     * <p>
     * Create tuple from iterable, starting from the specified index. Iterable
     * can have more (or less) elements than the tuple to be created.
     * </p>
     * 
     * @param <X> the iterable component type 
     * @param iterable the iterable to be converted to a tuple
     * @return the tuple
     */
    public static <X> Triplet<X,X,X> fromIterable(final Iterable<X> iterable, int index) {
        return fromIterable(iterable, index, false);
    }

    private static <X> Triplet<X,X,X> fromIterable(final Iterable<X> iterable, int index, final boolean exactSize) {
        
        if (iterable == null) {
            throw new IllegalArgumentException("Iterable cannot be null");
        }

        boolean tooFewElements = false; 
        
        X element0 = null;
        X element1 = null;
        X element2 = null;
        
        final Iterator<X> iter = iterable.iterator();
        
        int i = 0;
        while (i < index) {
            if (iter.hasNext()) {
                iter.next();
            } else {
                tooFewElements = true;
            }
            i++;
        }
        
        if (iter.hasNext()) {
            element0 = iter.next();
        } else {
            tooFewElements = true;
        }
        
        if (iter.hasNext()) {
            element1 = iter.next();
        } else {
            tooFewElements = true;
        }
        
        if (iter.hasNext()) {
            element2 = iter.next();
        } else {
            tooFewElements = true;
        }
        
        if (tooFewElements && exactSize) {
            throw new IllegalArgumentException("Not enough elements for creating a Triplet (3 needed)");
        }
        
        if (iter.hasNext() && exactSize) {
            throw new IllegalArgumentException("Iterable must have exactly 3 available elements in order to create a Triplet.");
        }
        
        return new Triplet<X,X,X>(element0, element1, element2);
        
    }

    public Triplet(
            final A value0,
            final B value1,
            final C value2) {
        super(value0, value1, value2);
        this.val0 = value0;
        this.val1 = value1;
        this.val2 = value2;
    }

    public A getValue0() {
        return this.val0;
    }

    public B getValue1() {
        return this.val1;
    }

    public C getValue2() {
        return this.val2;
    }

    @Override
    public int getSize() {
        return SIZE;
    }

	/*
	 * ………………
	 * ………………
	 * ………………
	 */

}

自定义工具类
通过重载with方法,可以自动根据传入的参数个数,返回相应的元组对象

public class TupleUtils {

    public static <A> Unit<A> with(final A value0){
        return Unit.with(value0);
    }

    public static <A, B> Pair<A, B> with(final A value0, final B value1){
        return Pair.with(value0, value1);
    }

    public static <A, B, C> Triplet<A, B, C> with(final A value0, final B value1, final C value2){
        return Triplet.with(value0, value1, value2);
    }
}

使用案例
现有实体类Student、Teaccher、Programmer,需要存储实体类的字节码文件、对应数据库表的主键名称、对应数据库表的毕业院校字段名称

我们可以通过再定义一个类的方式实现,但是如果还要再添加其他属性的话,又得重新定义

如果采用元组的方式实现,就可以有效避免

public class TupleTest {

    public static void main(String[] args) {
        List<Triplet<Class, String, String>> roleList = new ArrayList<Triplet<Class, String, String>>();

        Triplet<Class, String, String> studentTriplet = TupleUtils.with(Student.class, "sid", "graduate");
        Triplet<Class, String, String> teacherTriplet = TupleUtils.with(Teacher.class, "sid", "graduate");
        Triplet<Class, String, String> programmerTriplet = TupleUtils.with(Programmer.class, "sid", "graduate");

        roleList.add(studentTriplet);
        roleList.add(teacherTriplet);
        roleList.add(programmerTriplet);

        for (Triplet<Class, String, String> triplet : roleList) {
            System.out.println(triplet);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

313YPHU3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值