【Java数据结构与算法】第二十一章 元组
文章目录
- 【Java数据结构与算法】第二十一章 元组
- 1.概念
- 2.自定义元组
- 3.第三方Jar包
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á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);
}
}
}