• 【一起读源码】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;
    
    • 1
    • 2

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

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

    public final Iterator<Object> iterator() {
        return this.valueList.iterator();
    }
    
    • 1
    • 2
    • 3

    比较容易理解,把 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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    接下来看一下其中的 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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这个我认为不合理的地方就是最后的返回 -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];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    子类以 Pair 为例

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

    public Pair(
            final A value0, 
            final B value1) {
        super(value0, value1);
        this.val0 = value0;
        this.val1 = value1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    内部变量 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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    总结

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

    Smileyan
    2022.7.28 19:56

  • 相关阅读:
    How to solve matplotlib Chinese garbled characters in Ubuntu 22.04
    python---pickle模块
    C++避坑小知识&&错题笔记
    轻松安装vue脚手架的一个详细讲解
    从Spring中学到的【1】--读懂继承链
    性能分析-java虚拟机性能监控
    X METAVERSE PRO Launches Cloud Mining, Creating a “New Era of Mining Trend”
    csdn测开涨薪技术-Git原理及使用全套教程
    【论文阅读笔记】Supervised Contrastive Learning
    品牌低价的形式有哪些
  • 原文地址:https://blog.csdn.net/smileyan9/article/details/126034738