一起读源码1. Java 中元组 Tuple

Posted smile-yan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一起读源码1. Java 中元组 Tuple相关的知识,希望对你有一定的参考价值。

问题描述

使用 Java 做数据分析、机器学习的时候,常常需要对批量的数据进行处理,如果需要处理的数据的维度不超过10时,可以考虑使用 org.javatuples 提供的 Tuple 类工具。支持 1 - 10 的多维数据处理,支持数据泛型。除了常见的 Integer / String / Long / Double 还可以是自定义的数据类型。

总体分析

如图所示,总共 13 个类,13个接口。

先看接口非常简单,附带自己的泛型 X,然后提供一个自己的方法 X getValue0() … X getValue9() … getValue … getKey … getLabel.

所有的类的父类为抽象类 Tuple,注意该方法并没有包含任何泛型,而是实现了常见的三个接口:

  • Iterable
  • Serializable
  • Comparable

接下来要出场的子类就根据实际情况实现多个接口,返回对应的值。具体内容如下表所示:

类名参数数目
Unit1
Pair2
KeyValue2
LabelValue2
Triplet3
Quartet4
Quintet5
Sextet6
Septet7
Octet8
Ennead9
Decade10

父类 Tuple

Tuple 是一个抽象类,具有两个成员变量,如下:

private final Object[] valueArray;
private final List<Object> valueList;

私有变量外部不能直接访问,这两个变量的主要作用应该是用于 Iterable 遍历。

接着看 Tuple 对这个接口的实现:

public final Iterator<Object> iterator() 
    return this.valueList.iterator();

比较容易理解,把 Tuple 的 iterator 转移给它内部变量完成。

同样地看一下 contains 方法,这个同样容易理解:如果待查变量为 null 则直接返回 false,否则逐个遍历看看是不是相等。

public final boolean contains(final Object value) 
    for (final Object val : this.valueList) 
        if (val == null) 
            if (value == null) 
                return true;
            
         else 
            if (val.equals(value)) 
                return true;
            
        
    
    return false;

接下来看一下其中的 indexOf 方法,也就是找到数据对应的索引:

public final int indexOf(final Object value) 
    int i = 0;
    for (final Object val : this.valueList) 
        if (val == null) 
            if (value == null) 
                return i;
            
         else 
            if (val.equals(value)) 
                return i;
            
        
        i++;
    
    return -1;

这个我认为不合理的地方就是最后的返回 -1 ,应该定义一个常量,NOT_FOUNT = -1 更加合适。其他的没有什么可以解释的。

类似地看一下 lastIndexOf ,这个只是倒过来遍历一次。

到目前为止还不知道成员变量 valueArray 的作用,看下源码发现,主要是用于Tuple转换为 Array 和 getValue 时使用(遍历链表时间复杂度为 O ( N ) O(N) O(N) 而此时根据索引读数据时间复杂度为 O ( 1 ) O(1) O(1))。

public final Object[] toArray() 
    return this.valueArray.clone();

public final Object getValue(final int pos) 
    if (pos >= getSize()) 
        throw new IllegalArgumentException(
                "Cannot retrieve position " + pos + " in " + this.getClass().getSimpleName() + 
                ". Positions for this class start with 0 and end with " + (getSize() - 1));
    
    return this.valueArray[pos];

子类以 Pair 为例

构造函数只提供了一个 ,即全参数构造函数

public Pair(
        final A value0, 
        final B value1) 
    super(value0, value1);
    this.val0 = value0;
    this.val1 = value1;

内部变量 final A value1 和 final B value2 是 final 类型的,因此如果希望更新它们的值不能直接 set 而是需要重新 new Pair,当然在 Pair 类中已经提供了。

public <X> Pair<X,B> setAt0(final X value) 
    return new Pair<X,B>(
            value, this.val1);


public <X> Pair<A,X> setAt1(final X value) 
    return new Pair<A,X>(
            this.val0, value);

而其他的方法比较有意思的是从 Pair 到 Triplet 等等更高维度的,都有提供这些方法。方法同样是 return new Triplet … 这类的。

总结

作为读源码的开端,特别选了一个简单的、也挺好用的。希望能够帮到大家~~

Smileyan
2022.7.28 19:56

以上是关于一起读源码1. Java 中元组 Tuple的主要内容,如果未能解决你的问题,请参考以下文章

一起读源码1. Java 中元组 Tuple

Python中元组常用的方法都有哪些,分别有啥作用?

C#中元组对象Tuple的使用

python中元组常识,以及for 与 range 的用法!

关于Python中元组的问题

Java中元组的使用