!438 加入集合索引环形获取工具类RingIndexUtil

Merge pull request !438 from ZhouChuGang/v5-dev
This commit is contained in:
Looly 2021-10-14 01:13:16 +00:00 committed by Gitee
commit 8c5577ab45
2 changed files with 151 additions and 0 deletions

View File

@ -0,0 +1,100 @@
package cn.hutool.core.collection;
import cn.hutool.core.lang.Assert;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* 集合索引环形获取工具类
*
* @author ZhouChuGang
* @since 5.7.15
*/
public class RingIndexUtil {
/**
* 通过cas操作 实现对指定值内的回环累加
*
* @param object 集合
* <ul>
* <li>Collection - the collection size
* <li>Map - the map size
* <li>Array - the array size
* <li>Iterator - the number of elements remaining in the iterator
* <li>Enumeration - the number of elements remaining in the enumeration
* </ul>
* @param atomicLong 原子操作类
* @return 索引位置
*/
public static long ringNextLongByObj(Object object, AtomicLong atomicLong) {
Assert.notNull(object);
int modulo = CollUtil.size(object);
return ringNextLong(modulo, atomicLong);
}
/**
* 通过cas操作 实现对指定值内的回环累加
*
* @param object 集合
* <ul>
* <li>Collection - the collection size
* <li>Map - the map size
* <li>Array - the array size
* <li>Iterator - the number of elements remaining in the iterator
* <li>Enumeration - the number of elements remaining in the enumeration
* </ul>
* @param atomicInteger 原子操作类
* @return 索引位置
*/
public static int ringNextIntByObj(Object object, AtomicInteger atomicInteger) {
Assert.notNull(object);
int modulo = CollUtil.size(object);
return ringNextInt(modulo, atomicInteger);
}
/**
* 通过cas操作 实现对指定值内的回环累加
*
* @param modulo 回环周期值
* @param atomicInteger 原子操作类
* @return 索引位置
*/
public static int ringNextInt(int modulo, AtomicInteger atomicInteger) {
Assert.notNull(atomicInteger);
Assert.isTrue(modulo > 0);
if (modulo == 1) {
return 0;
}
for (; ; ) {
int current = atomicInteger.get();
int next = (current + 1) % modulo;
if (atomicInteger.compareAndSet(current, next)) {
return next;
}
}
}
/**
* 通过cas操作 实现对指定值内的回环累加
*
* @param modulo 回环周期值
* @param atomicLong 原子操作类
* @return 索引位置
*/
public static long ringNextLong(long modulo, AtomicLong atomicLong) {
Assert.notNull(atomicLong);
Assert.isTrue(modulo > 0);
if (modulo == 1) {
return 0;
}
for (; ; ) {
long current = atomicLong.get();
long next = (current + 1) % modulo;
if (atomicLong.compareAndSet(current, next)) {
return next;
}
}
}
}

View File

@ -0,0 +1,51 @@
package cn.hutool.core.collection;
import cn.hutool.core.thread.ThreadUtil;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* 集合索引环形获取工具类测试类
*
* @author ZhouChuGang
* @version 1.0
* @project hutool
* @date 2021/10/13 18:47
*/
public class RingIndexUtilTest {
private final List<String> strList = Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
/**
* 观察输出的打印为不重复的
*/
@Test
public void ringNextLongByObjTest() {
final AtomicLong atomicLong = new AtomicLong();
// 开启并发测试每个线程获取到的元素都是唯一的
ThreadUtil.concurrencyTest(strList.size(), () -> {
final long index = RingIndexUtil.ringNextLongByObj(strList, atomicLong);
final String s = strList.get((int) index);
System.out.println(s);
});
}
/**
* 观察输出的打印为不重复的
*/
@Test
public void ringNextIntByObjTest() {
final AtomicInteger atomicInteger = new AtomicInteger();
// 开启并发测试每个线程获取到的元素都是唯一的
ThreadUtil.concurrencyTest(strList.size(), () -> {
final int index = RingIndexUtil.ringNextIntByObj(strList, atomicInteger);
final String s = strList.get(index);
System.out.println(s);
});
}
}