ObjectUtils.java

编程

import lombok.extern.slf4j.Slf4j;

import com.donkeycode.core.io.FastByteArrayOutputStream;

import java.io.ByteArrayInputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.lang.reflect.Array;

import java.lang.reflect.InvocationTargetException;

import java.util.*;

import org.springframework.cglib.beans.BeanCopier;

/**

* 对象操作工具类

*

* @author nanfeng

* @date 2019年12月10日

* @since 0.0.1

*/

@Slf4j

public class ObjectUtils {

/**

* 比较两个对象是否相等。<br>

* 相同的条件有两个,满足其一即可:<br>

* <code>

* 1. obj1 == null &amp;&amp; obj2 == null;

* 2. obj1.equals(obj2)

* </code>

*

* @param obj1

* 对象1

* @param obj2

* 对象2

* @return 是否相等

*/

public static boolean equals(Object obj1, Object obj2) {

return Objects.equals(obj1, obj2);

}

/**

* <p>计算对象长度,如果是字符串调用其length函数,集合类调用其size函数,数组调用其length属性,其他可遍历对象遍历计算长度</p>

*

* @param obj

* 被计算长度的对象

* @return 长度

*/

public static int length(Object obj) {

if (obj == null) {

return 0;

}

if (obj instanceof CharSequence) {

return ((CharSequence) obj).length();

}

if (obj instanceof Collection) {

return ((Collection<?>) obj).size();

}

if (obj instanceof Map) {

return ((Map<?, ?>) obj).size();

}

int count;

if (obj instanceof Iterator) {

Iterator<?> iter = (Iterator<?>) obj;

count = 0;

while (iter.hasNext()) {

count++;

iter.next();

}

return count;

}

if (obj instanceof Enumeration) {

Enumeration<?> enumeration = (Enumeration<?>) obj;

count = 0;

while (enumeration.hasMoreElements()) {

count++;

enumeration.nextElement();

}

return count;

}

if (obj.getClass().isArray() == true) {

return Array.getLength(obj);

}

return -1;

}

/**

* 对象中是否包含元素

*

* @param obj

* 对象

* @param element

* 元素

* @return 是否包含

*/

public static boolean contains(Object obj, Object element) {

if (obj == null) {

return false;

}

if (obj instanceof String) {

if (element == null) {

return false;

}

return ((String) obj).contains(element.toString());

}

if (obj instanceof Collection) {

return ((Collection<?>) obj).contains(element);

}

if (obj instanceof Map) {

return ((Map<?, ?>) obj).values().contains(element);

}

if (obj instanceof Iterator) {

Iterator<?> iter = (Iterator<?>) obj;

while (iter.hasNext()) {

Object o = iter.next();

if (equals(o, element)) {

return true;

}

}

return false;

}

if (obj instanceof Enumeration) {

Enumeration<?> enumeration = (Enumeration<?>) obj;

while (enumeration.hasMoreElements()) {

Object o = enumeration.nextElement();

if (equals(o, element)) {

return true;

}

}

return false;

}

if (obj.getClass().isArray() == true) {

int len = Array.getLength(obj);

for (int i = 0; i < len; i++) {

Object o = Array.get(obj, i);

if (equals(o, element)) {

return true;

}

}

}

return false;

}

/**

* 检查对象是否为null

*

* @param obj

* 对象

* @return 是否为null

*/

public static boolean isNull(Object obj) {

return Objects.isNull(obj);

}

/**

* 检查对象是否不为null

*

* @param obj

* 对象

* @return 是否为null

*/

public static boolean isNotNull(Object obj) {

return !isNull(obj);

}

/**

* 克隆对象<br>

* <p> 对象必须实现Serializable接口</p>

*

* @param obj

* @return

*/

@SuppressWarnings("unchecked")

public static <T> T clone(T obj) {

final FastByteArrayOutputStream byteOut = new FastByteArrayOutputStream();

try (ObjectOutputStream out = new ObjectOutputStream(byteOut)) {

out.writeObject(obj);

out.flush();

final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(byteOut.toByteArray()));

return (T) in.readObject();

} catch (Exception e) {

log.error(e.getMessage(), e);

throw new RuntimeException(e);

}

}

/**

* 序列化<br>

* 对象必须实现Serializable接口

*

* @param <T>

* @param t

* 要被序列化的对象

* @return 序列化后的字节码

*/

public static <T> byte[] serialize(T t) {

FastByteArrayOutputStream byteOut = new FastByteArrayOutputStream();

try (ObjectOutputStream oos = new ObjectOutputStream(byteOut)) {

oos.writeObject(t);

oos.flush();

} catch (Exception e) {

log.error(e.getMessage(), e);

throw new RuntimeException(e);

}

return byteOut.toByteArray();

}

/**

* 反序列化<br>

* 对象必须实现Serializable接口

*

* @param <T>

* @param bytes

* 反序列化的字节码

* @return 反序列化后的对象

*/

@SuppressWarnings("unchecked")

public static <T> T unserialize(byte[] bytes) {

try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais)) {

return (T) ois.readObject();

} catch (Exception e) {

log.error(e.getMessage(), e);

throw new RuntimeException(e);

}

}

/**

* 检查是否为有效的数字<br>

* 检查Double和Float是否为无限大,或者Not a Number<br>

* 非数字类型和Null将返回true

*

* @param obj

* 被检查类型

* @return 检查结果,非数字类型和Null将返回true

*/

public static boolean isValidIfNumber(Object obj) {

if (obj != null && obj instanceof Number) {

if (obj instanceof Double) {

if (((Double) obj).isInfinite() || ((Double) obj).isNaN()) {

return false;

}

} else if (obj instanceof Float) {

if (((Float) obj).isInfinite() || ((Float) obj).isNaN()) {

return false;

}

}

}

return true;

}

/**

* 将List中的对象拷贝到目标对象的List中(标准Bean)

*

* @param sourceList

* 源List

* @param targetCls

* 目标对象类型

* @param <T>

* 源类型

* @param <R>

* 目标类型

* @return 目标类型List数组

*/

public static <T, R> List<R> beanCopyPropertiesForList(List<T> sourceList, Class<R> targetCls) {

List<R> targetList = new ArrayList<R>();

if (sourceList != null && !sourceList.isEmpty()) {

for (T source : sourceList) {

targetList.add(beanCopyProperties(source, targetCls));

}

}

return targetList;

}

/**

* 属性值拷贝(标准Bean)

*

* @param source

* 源对象

* @param targetCls

* 目标对象类

* @return 拷贝目标类的实体

*/

public static <R> R beanCopyProperties(Object source, Class<R> targetCls) {

try {

R target = targetCls.getDeclaredConstructor().newInstance();

BeanCopier copier = BeanCopier.create(source.getClass(), targetCls, false);

if (source != null) {

copier.copy(source, target, null);

}

return target;

} catch (InstantiationException e) {

log.error(e.getMessage(), e);

throw new RuntimeException("Instantiation target error.");

} catch (IllegalAccessException e) {

log.error(e.getMessage(), e);

throw new RuntimeException("Target Illegal Access error.");

} catch (InvocationTargetException e) {

log.error(e.getMessage(), e);

throw new RuntimeException("Invocation Target error.");

} catch (NoSuchMethodException e) {

log.error(e.getMessage(), e);

throw new RuntimeException("Target class No Such Method error.");

}

}

}

import java.io.IOException;

import java.io.OutputStream;

import java.io.UnsupportedEncodingException;

import java.nio.charset.Charset;

/**

* 基于快速缓冲FastByteBuffer的OutputStream,随着数据的增长自动扩充缓冲区

* <p>

* 可以通过{@link #toByteArray()}和 {@link #toString()}来获取数据

* <p>

* {@link #close()}方法无任何效果,当流被关闭后不会抛出IOException

* <p>

* 这种设计避免重新分配内存块而是分配新增的缓冲区,缓冲区不会被GC,数据也不会被拷贝到其他缓冲区。

*

* @author biezhi

*/

public class FastByteArrayOutputStream extends OutputStream {

private final FastByteBuffer buffer;

public FastByteArrayOutputStream() {

this(1024);

}

public FastByteArrayOutputStream(int size) {

buffer = new FastByteBuffer(size);

}

@Override

public void write(byte[] b, int off, int len) {

buffer.append(b, off, len);

}

@Override

public void write(int b) {

buffer.append((byte) b);

}

public int size() {

return buffer.size();

}

/**

* 此方法无任何效果,当流被关闭后不会抛出IOException

*/

@Override

public void close() {

// nop

}

public void reset() {

buffer.reset();

}

public void writeTo(OutputStream out) throws IOException {

int index = buffer.index();

for (int i = 0; i < index; i++) {

byte[] buf = buffer.array(i);

out.write(buf);

}

out.write(buffer.array(index), 0, buffer.offset());

}

public byte[] toByteArray() {

return buffer.toArray();

}

@Override

public String toString() {

return new String(toByteArray());

}

public String toString(String enc) throws UnsupportedEncodingException {

return new String(toByteArray(), enc);

}

public String toString(Charset charset) {

return new String(toByteArray(), charset);

}

}

/**

* 代码移植自<a href="https://github.com/biezhi/blade">blade</a><br>

* 快速缓冲,将数据存放在缓冲集中,取代以往的单一数组

*

* @author yanjun.xue

* @since 1.0

*/

public class FastByteBuffer {

/**

* 缓冲集

*/

private byte[][] buffers = new byte[16][];

/**

* 缓冲数

*/

private int buffersCount;

/**

* 当前缓冲索引

*/

private int currentBufferIndex = -1;

/**

* 当前缓冲

*/

private byte[] currentBuffer;

/**

* 当前缓冲偏移量

*/

private int offset;

/**

* 缓冲字节数

*/

private int size;

/**

* 一个缓冲区的最小字节数

*/

private final int minChunkLen;

public FastByteBuffer() {

this.minChunkLen = 1024;

}

public FastByteBuffer(int size) {

this.minChunkLen = Math.abs(size);

}

/**

* 分配下一个缓冲区,不会小于1024

*

* @param newSize

* 理想缓冲区字节数

*/

private void needNewBuffer(int newSize) {

int delta = newSize - size;

int newBufferSize = Math.max(minChunkLen, delta);

currentBufferIndex++;

currentBuffer = new byte[newBufferSize];

offset = 0;

// add buffer

if (currentBufferIndex >= buffers.length) {

int newLen = buffers.length << 1;

byte[][] newBuffers = new byte[newLen][];

System.arraycopy(buffers, 0, newBuffers, 0, buffers.length);

buffers = newBuffers;

}

buffers[currentBufferIndex] = currentBuffer;

buffersCount++;

}

/**

* 向快速缓冲加入数据

*

* @param array

* 数据

* @param off

* 偏移量

* @param len

* 字节数

* @return 快速缓冲自身 @see FastByteBuffer

*/

public FastByteBuffer append(byte[] array, int off, int len) {

int end = off + len;

if ((off < 0) || (len < 0) || (end > array.length)) {

throw new IndexOutOfBoundsException();

}

if (len == 0) {

return this;

}

int newSize = size + len;

int remaining = len;

if (currentBuffer != null) {

// first try to fill current buffer

int part = Math.min(remaining, currentBuffer.length - offset);

System.arraycopy(array, end - remaining, currentBuffer, offset, part);

remaining -= part;

offset += part;

size += part;

}

if (remaining > 0) {

// still some data left

// ask for new buffer

needNewBuffer(newSize);

// then copy remaining

// but this time we are sure that it will fit

int part = Math.min(remaining, currentBuffer.length - offset);

System.arraycopy(array, end - remaining, currentBuffer, offset, part);

offset += part;

size += part;

}

return this;

}

/**

* 向快速缓冲加入数据

*

* @param array

* 数据

* @return 快速缓冲自身 @see FastByteBuffer

*/

public FastByteBuffer append(byte[] array) {

return append(array, 0, array.length);

}

/**

* 向快速缓冲加入一个字节

*

* @param element

* 一个字节的数据

* @return 快速缓冲自身 @see FastByteBuffer

*/

public FastByteBuffer append(byte element) {

if ((currentBuffer == null) || (offset == currentBuffer.length)) {

needNewBuffer(size + 1);

}

currentBuffer[offset] = element;

offset++;

size++;

return this;

}

/**

* 将另一个快速缓冲加入到自身

*

* @param buff

* 快速缓冲

* @return 快速缓冲自身 @see FastByteBuffer

*/

public FastByteBuffer append(FastByteBuffer buff) {

if (buff.size == 0) {

return this;

}

for (int i = 0; i < buff.currentBufferIndex; i++) {

append(buff.buffers[i]);

}

append(buff.currentBuffer, 0, buff.offset);

return this;

}

public int size() {

return size;

}

public boolean isEmpty() {

return size == 0;

}

/**

* 当前缓冲位于缓冲区的索引位

*

* @return {@link #currentBufferIndex}

*/

public int index() {

return currentBufferIndex;

}

public int offset() {

return offset;

}

/**

* 根据索引位返回缓冲集中的缓冲

*

* @param index

* 索引位

* @return 缓冲

*/

public byte[] array(int index) {

return buffers[index];

}

public void reset() {

size = 0;

offset = 0;

currentBufferIndex = -1;

currentBuffer = null;

buffersCount = 0;

}

/**

* 返回快速缓冲中的数据

*

* @return 快速缓冲中的数据

*/

public byte[] toArray() {

int pos = 0;

byte[] array = new byte[size];

if (currentBufferIndex == -1) {

return array;

}

for (int i = 0; i < currentBufferIndex; i++) {

int len = buffers[i].length;

System.arraycopy(buffers[i], 0, array, pos, len);

pos += len;

}

System.arraycopy(buffers[currentBufferIndex], 0, array, pos, offset);

return array;

}

/**

* 返回快速缓冲中的数据

*

* @param start

* 逻辑起始位置

* @param len

* 逻辑字节长

* @return 快速缓冲中的数据

*/

public byte[] toArray(int start, int len) {

int remaining = len;

int pos = 0;

byte[] array = new byte[len];

if (len == 0) {

return array;

}

int i = 0;

while (start >= buffers[i].length) {

start -= buffers[i].length;

i++;

}

while (i < buffersCount) {

byte[] buf = buffers[i];

int c = Math.min(buf.length - start, remaining);

System.arraycopy(buf, start, array, pos, c);

pos += c;

remaining -= c;

if (remaining == 0) {

break;

}

start = 0;

i++;

}

return array;

}

/**

* 根据索引位返回一个字节

*

* @param index

* 索引位

* @return 一个字节

*/

public byte get(int index) {

if ((index >= size) || (index < 0)) {

throw new IndexOutOfBoundsException();

}

int ndx = 0;

while (true) {

byte[] b = buffers[ndx];

if (index < b.length) {

return b[index];

}

ndx++;

index -= b.length;

}

}

}

以上是 ObjectUtils.java 的全部内容, 来源链接: utcz.com/z/518023.html

回到顶部