概述

Java的原生类型就是指基本类型:byte、short、int、long、float、double、char和boolean。


  • 基本类型byte: 8位 -128~127

  • 基本类型char char 是字符数据类型 ,是无符号型的,占2字节(Unicode码),大小范围 是0—65535;char是一个16位二进制的Unicode字符,JAVA用char来表示一个字符 。Java是用unicode来表示字符,”中”这个中文字符的unicode就是2个字节。通常gbk/gb2312是2个字节,utf-8是3个字节。如果不指定encoding则取系统默认的encoding。

  • 基本类型:short 二进制位数:16
    包装类:java.lang.Short
    最小值:Short.MIN_VALUE=-32768 (-2的15此方)
    最大值:Short.MAX_VALUE=32767 (2的15次方-1)

  • 基本类型:int 二进制位数:32
    包装类:java.lang.Integer
    最小值:Integer.MIN_VALUE= -2147483648 (-2的31次方)
    最大值:Integer.MAX_VALUE= 2147483647 (2的31次方-1)

  • 基本类型:long 二进制位数:64
    包装类:java.lang.Long
    最小值:Long.MIN_VALUE=-9223372036854775808 (-2的63次方)
    最大值:Long.MAX_VALUE=9223372036854775807 (2的63次方-1)

  • 基本类型:float 二进制位数:32
    包装类:java.lang.Float

  • 基本类型:double 二进制位数:64
    包装类:java.lang.Double

  • float的小数点后6位,double的小数点后16位。

  • 建议:在从Guava查找原生类型方法之前,可以先查查Arrays类,或者对应的基础类型包装类,如Integer,Float。Integer是一个类,是int的扩展,定义了很多的转换方法类似的还有float,Float;doubleDouble;String等,其中String较为特殊,基本类型和复杂类似关键字相同。


Guava原声类型的支持

  • 意义:原生类型不能当作对象或泛型的类型参数使用,这意味着许多通用方法都不能应用于它们。Guava提供了若干通用工具,包括原生类型数组与集合API的交互,原生类型和字节数组的相互转换,以及对某些原生类型的无符号形式的支持。

支持的所有的:

原生类型

Guava工具类(都在com.google.common.primitives包)

byte

Bytes, SignedBytes, UnsignedBytes

short

Shorts

int

Ints, UnsignedInteger, UnsignedInts

long

Longs, UnsignedLong, UnsignedLongs

float

Floats

double

Doubles

char

Chars

boolean

Booleans

Bytes工具类没有定义任何区分有符号和无符号字节的方法,而是把它们都放到了SignedBytes和UnsignedBytes工具类中,因为字节类型的符号性比起其它类型要略微含糊一些。

int和long的无符号形式方法在UnsignedInts和UnsignedLongs类中,但由于这两个类型的大多数用法都是有符号的,Ints和Longs类按照有符号形式处理方法的输入参数。

此外,Guava为int和long的无符号形式提供了包装类,即UnsignedInteger和UnsignedLong,以帮助你使用类型系统,以极小的性能消耗对有符号和无符号值进行强制转换。

在本章下面描述的方法签名中,我们用Wrapper表示JDK包装类,prim表示原生类型。(Prims表示相应的Guava工具类。)

Bytes

把数组转为相应包装类的List


  1. List asList(prim… backingArray)
  2. Arrays.asList类似这个

//这个是包装数组,不然会报错的 JDK的
List<Byte> listByte = Arrays.asList(new Byte[]{1,2,3});

//这个是原生的数据没得事 Guava的
List<Byte> listbyte = Bytes.asList(new byte[]{1,2,3});

JDK的实现:使用了ArrayList

public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}

Guava的实现,自己继承抽象List,新的List的实现

public static List<Byte> asList(byte... backingArray) {
if (backingArray.length == 0) {
return Collections.emptyList();
}
return new ByteArrayAsList(backingArray);
}

这里自己实现的ByteArrayAsList和Collections.emptyList一样的,都是重写了一个immutalbe-list

EmptyList

public static final List EMPTY_LIST = new EmptyList<>();
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
// immtable 的emptyList 很多的额权限都没得哈哈
private static class EmptyList<E>
extends AbstractList<E>
implements RandomAccess, Serializable {

public Iterator<E> iterator() {
return emptyIterator();
}
public ListIterator<E> listIterator() {
return emptyListIterator();
}

public int size() {return 0;}
public boolean isEmpty() {return true;}

public boolean contains(Object obj) {return false;}
public boolean containsAll(Collection<?> c) { return c.isEmpty(); }

public Object[] toArray() { return new Object[0]; }

public <T> T[] toArray(T[] a) {
if (a.length > 0)
a[0] = null;
return a;
}

public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}

public boolean equals(Object o) {
return (o instanceof List) && ((List<?>)o).isEmpty();
}

public int hashCode() { return 1; }
}

Guava Bytes中的内部类的处理,保存的是原生的byte,sublist也是使用同一个list,没有进行数据的复制,但是不是线程安全的类!

private static class ByteArrayAsList extends AbstractList<Byte>
implements RandomAccess, Serializable {
final byte[] array;
final int start;
final int end;

ByteArrayAsList(byte[] array) {
this(array, 0, array.length);
}

ByteArrayAsList(byte[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}

@Override
public int size() {
return end - start;
}

@Override
public boolean isEmpty() {
return false;
}
//只有Get的使用才是转换为Byte封装类
@Override
public Byte get(int index) {
checkElementIndex(index, size());
return array[start + index];
}

@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Byte)
&&
Bytes.indexOf(array, (Byte) target, start, end) != -1;
}

@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Byte) {
int i = Bytes.indexOf(array, (Byte) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}

@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Byte) {
int i = Bytes.lastIndexOf(array, (Byte) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public Byte set(int index, Byte element) {
checkElementIndex(index, size());
byte oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
array[start + index] = checkNotNull(element);
return oldValue;
}

@Override
public List<Byte> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
return Collections.emptyList();
}//使用同一个数组
return new ByteArrayAsList(array, start + fromIndex, start + toIndex);
}
//使用JDK的
byte[] toByteArray() {
return Arrays.copyOfRange(array, start, end);
}
private static final long serialVersionUID = 0;
}

Guava Bytes中方法


  • 查找 int indexOf(prim[] array, prim target)
  • 给定值在数组中首次出现处的索引,若不包含此值返回-1
  • 类似 List.indexOf

public static int indexOf(byte[] array, byte target) {
return indexOf(array, target, 0, array.length);
}
private static int indexOf(byte[] array, byte target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
private static int lastIndexOf(byte[] array, byte target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}

  • 连接,这种操作,都是基于原生的类型进行处理的!
  • prim[] concat(prim[]… arrays)
  • 串联多个原生类型数组
  • 类似方法:Iterables.concat

public static byte[] concat(byte[]... arrays) {
int length = 0;
for (byte[] array : arrays) {
length += array.length;
}
byte[] result = new byte[length];
int pos = 0;
for (byte[] array : arrays) {
System.arraycopy(array, 0, result, pos, array.length);
pos += array.length;
}
return result;
}

把集合拷贝为数组,和collection.toArray()一样线程安全


  1. prim[] toArray(Collection collection)
  2. Collection.toArray() 类似这个方法

JDK中集合toArray

List<Integer> list =Arrays.asList(1,2,3,45);
Integer[] a = (Integer[]) list.toArray();

//这里是Object对象,转换为其他的还要报错。
//只能和当前的数组类型相关的包装类
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
//而且这里只能转换为包装类

看看Bytes中的实现,将Collection转换为基本类型的byte[]

List<Integer> list =Arrays.asList(1,2,3,256);
byte[] changByBytes = Bytes.toArray(list);
for(int i=0;i < changByBytes.length;i++){
System.out.println("i:"+changByBytes[i]);
}
i:1
i:2
i:3
i:0

怎么样不错吧,哈哈,速度可以的~

先看看JDK Number接口,各种包装类都继承这个玩意


用于在原始类型之间转换。因此,转换可能丢失有关数值的整体大小的信息,失去精度,甚至可能返回一个不同的标志的结果。


public abstract class Number implements java.io.Serializable {

public abstract int intValue();

public abstract long longValue();

public abstract float floatValue();

public abstract double doubleValue();

public byte byteValue() {
return (byte)intValue();
}
public short shortValue() {
return (short)intValue();
}
}

这里还是使用collection.toArray,然后转换为byte,这个可能会失去精度!优势在哪里,返回原生的数据类型。

public static byte[] toArray(Collection< ? extends Number> collection) {
if (collection instanceof ByteArrayAsList) {
return ((ByteArrayAsList) collection).toByteArray();
}

Object[] boxedArray = collection.toArray();
int len = boxedArray.length;
byte[] array = new byte[len];
for (int i = 0; i < len; i++) {
// checkNotNull for GWT (do not optimize)
array[i] = ((Number) checkNotNull(boxedArray[i])).byteValue();
}
return array;
}

数组中最小大的值


  • prim min(prim… array) prim max(prim… array)
  • Collections.max 类似这个
  • 不过这个是对于原生的数组
    Ints中的哦!

public static int min(int... array) {
checkArgument(array.length > 0);
int min = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
}
}
return min;
}

把数组用给定分隔符连接为字符串


  • String join(String separator, prim… array)
  • Joiner.on(separator).join 类似这个(不过这个要强大一点)
    Ints中的哦!

public static String join(String separator, int... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}

// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * 5);
builder.append(array[0]);
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(array[i]);
}
return builder.toString();
}

把int转换为byte数组

public static byte[] toByteArray(int value) {
return new byte[] {
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value
};
}

把byte转换为int

public static int fromByteArray(byte[] bytes) {
checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
return fromBytes(bytes[0], bytes[1], bytes[2], bytes[3]);
}
public static int fromBytes(byte b1, byte b2, byte b3, byte b4) {
return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | (b4 & 0xFF);
}