今天在研读mahout的cf算法时,看到了一小段代码,是用apache.Math.Vector数据类型,由于之前没有使用过vector,所以查了一下相关资料,在这里总结一下。从java Vector说起。
java.util.Vector类
继承了Object类,实现了Cloneable和Serializable 类,实现了可动态扩充的对象数组。类似数组,它包含的元素可通过数组下标来访问。但是,在Vector
创建之后。Vector
可根据增加和删除元素的需要来扩大或缩小。
每个向量可通过维护 capacity
和 capacityIncrement
来优化存储空间的管理。capacity
至少和向量大小一样大;但它通常会更大些,因为向量会添加组件,向量的存储空间会根据capacityIncrement
增加。应用在插入大数量的组件之前会增加向量的容量;这减少了再分配的数量。
import java.util.Vector;
public class test_vector {
public static void main(String[] args) {
// TODO Auto-generated method stub
Vector vec = new Vector(3,5) ; //构造函数的第一个参数为向量的初始容量,第二个为空间溢出时的动态增加量
vec.add("akdjf"); //String 类型的元素
vec.add(5); //int 类型的元素
for (int i = 0; i < vec.size(); i++) {
System.out.println(vec.get(i));
}
}
}
说明:
1.Vector的add方法的参数类型为Object,也就是说,如上例,向向量中增加元素的时候不必考虑是什么类型的,完全可以被接纳。
2.Vector.get(int index)方法即为上述所讲,使用下标访问向量元素。
也就是说,java的向量是个非常方便的动态数组,当你需要存储多种元素,同时希望对这些数据进行查询操作,那么向量是个非常好的选择。
挑几个好用的方法介绍一下:.
1.copyInto
public final synchronized void copyInto(ObjectanArray[])
把该向量的元素复制到指定数组中。 数组必须足够大到可容纳向量中的所有对象。
参数:anArray - 放复制元素的数组。
2.trimToSize
public final synchronized void trimToSize()
把该向量的容量调整为向量的当前大小。应用可使用该操作最小化向量存储空间。
3.contains
public final boolean contains(Object elem)
-
测试指定对象是该向量的一个元素。
-
参数:
- elem - 一个对象。 返回值:
-
如果指定对象是该向量中的一个元素,则返回
true
;否则返回false
。
4.setElementAt
public final synchronized void setElementAt(Object obj,int index)
-
设置在向量中指定的
index
处的元素为指定的对象。 在该位置的先前元素被抛弃。 -
下标值必须大于或等于
0
,并且小于向量的当前大小。 -
-
参数:
- obj - 元素被设置成的那个对象。
- index - 指定下标。 抛出: ArrayIndexOutOfBoundsException
- 如果下标无效。
再来说说mahout的Vector。mahout的Vector是个接口,它继承了java.lang.Cloneable接口,java.util.Iterator类,并没有继承java.util.Vector类。
public interface Vector
extends Cloneable, Iterable
{
public static interface Element
{
public abstract double get();
public abstract int index();
public abstract void set(double d);
}
public abstract String asFormatString();
public abstract Vector assign(double d);
public abstract Vector assign(double ad[]);
public abstract Vector assign(Vector vector);
public abstract Vector assign(DoubleFunction doublefunction);
public abstract Vector assign(Vector vector, DoubleDoubleFunction doubledoublefunction);
public abstract Vector assign(DoubleDoubleFunction doubledoublefunction, double d);
public abstract int size();
public abstract boolean isDense();
public abstract boolean isSequentialAccess();
public abstract Vector clone();
public abstract Iterator iterator();
public abstract Iterator iterateNonZero();
public abstract Element getElement(int i);
public abstract Vector divide(double d);
public abstract double dot(Vector vector);
public abstract double get(int i);
public abstract double getQuick(int i);
public abstract Vector like();
public abstract Vector minus(Vector vector);
public abstract Vector normalize();
public abstract Vector normalize(double d);
public abstract Vector logNormalize();
public abstract Vector logNormalize(double d);
public abstract double norm(double d);
public abstract double minValue();
public abstract int minValueIndex();
public abstract double maxValue();
public abstract int maxValueIndex();
public abstract Vector plus(double d);
public abstract Vector plus(Vector vector);
public abstract void set(int i, double d);
public abstract void setQuick(int i, double d);
public abstract int getNumNondefaultElements();
public abstract Vector times(double d);
public abstract Vector times(Vector vector);
public abstract Vector viewPart(int i, int j);
public abstract double zSum();
public abstract Matrix cross(Vector vector);
public abstract double aggregate(DoubleDoubleFunction doubledoublefunction, DoubleFunction doublefunction);
public abstract double aggregate(Vector vector, DoubleDoubleFunction doubledoublefunction, DoubleDoubleFunction doubledoublefunction1);
public abstract double getLengthSquared();
public abstract double getDistanceSquared(Vector vector);
}
这里体现了面相对象的一大特征:封装----1.划定权限控制,将权限的边界划在数据类型内部,可以在结构内部建立自己的内部机制,而不必担心客户端程序员会偶然将内部机制当做是他们可以使用的接口的一部分;2.讲接口与具体实现进行分离,
先来看看我读到的那段代码:
public static class ToUserVectorReducer extends Reducer
<VLongWritable, IntWritable, VLongWritable, VectorWritable> {
<strong><span style="color:#ff0000;">private Vector userVector;
</span></strong> private VectorWritable userVectorWritable = new VectorWritable();
@Override
protected void reduce(VLongWritable userID, Iterable<IntWritable> itemPrefs,
Context context) throws IOException, InterruptedException {
// TODO Auto-generated method stub
<span style="color:#ff0000;">userVector = new RandomAccessSparseVector(Integer.MAX_VALUE, 100000);
</span> for (IntWritable itemPref : itemPrefs) {
<span style="color:#ff0000;">userVector.set(Integer.parseInt(itemPref.toString()), 1.0f);
</span> }
userVectorWritable.set(userVector);
context.write(userID, userVectorWritable);
}
}
代码中的userVector.set(Integer.parseInt(itemPref.toString()), 1.0f)方法就类似于java.Vector的