apache commons-collections

213 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情

集合工具类

许多开源机构为我们提供了操作集合的工具类。

apache

Apache.commons下的commons-collectionsX包对java集合框架(java collection framework)做扩展。

image-20220818094842448.png

  • Bag - 简化了一个对象在集合中存在多个副本的操作
  • BidiMap - 提供双向映射,可通过键查找值,也可以通过值查找键
  • Iterators - 方便迭代
Bag

Bag简化了一个对象存在多个副本的操作。

HashBag & TreeBag

hashBag & TreeBag的继承关系如下图所示:

TreeBag 相较于HashBag多实现一个接口 : SortedBag即表现为一个有序的bag。

HashBag其内封装了一个HashMap,key是元素,value是元素个数。

TreeMap其内封装了一个TreeMap,key是元素,value是元素个数。

image-20220818151047171.png

hashBag&TreeBag的创建。

public HashBag() {
    super(new HashMap<E, MutableInteger>());
}
public HashBag(final Collection<? extends E> coll) {
    this();
    addAll(coll);
}

private transient Map<E, MutableInteger> map;
protected AbstractMapBag(final Map<E, MutableInteger> map) {
    super();
    this.map = map;
}

hashBag&TreeBag基本使用3

/**
 * hashBag底层是一个hashMap 元素是key值,添加个数是value
 * 可以通过add(object,nCopies)方法为每个元素添加n个副本
 * 如果add两次则会跟新value值(加一)
 */
StringBuilder sb1 = new StringBuilder("a");
StringBuilder sb2 = new StringBuilder("b");
StringBuilder sb3 = new StringBuilder("c");
Bag<Object> hashBag = new HashBag<>();

hashBag.add(sb1);
hashBag.add(sb1);
hashBag.add(sb2, 3);
hashBag.add(sb3, 3);
System.out.println("Bag+元素个数:" + hashBag.size());
System.out.println("Bag中sb1个数:" + hashBag.getCount(sb1));
String result1 = hashBag.stream().map(Object::toString).collect(Collectors.joining(",", "[", "]"));
System.out.println("HashBag 内容:" + result1);
//可以使用Collection作为构造方法参数
Bag<Object> hashBag2 = new HashBag<>(Arrays.asList("1", "2", "3"));
String result3 = hashBag2.stream().map(Object::toString).collect(Collectors.joining(",", "[", "]"));
System.out.println("hashBag2 内容:" + result3);

/**
 * TreeBag:底层封装了一个TreeMap。
 * 其实可依发现HashBag中的元素是无序的,那么TreeBag就是一个有序的Bag
 */
TreeBag<String> treeBag = new TreeBag<>(Arrays.asList("99", "2", "3", "7"));
String result2 = treeBag.stream().map(Object::toString).collect(Collectors.joining(",", "[", "]"));
System.out.println("TreeBag 内容:" + result2);

CollectionBag

CollectionBag没有无参构造,必须依赖一个Bag类型的参数。CollectionBag只是对Bag的封装,任何操作实际上操作的是封装的Bag。

/**
 * CollectionBag的创建依赖于现有Bag,不可使用Collection作为构造方法参数
 *
 * 其内方法是对Bag的一层封装,实际调用的还是Bag的方法
 */
Bag<Object> collectionBag = CollectionBag.collectionBag(hashBag);
String result4 = collectionBag.stream().map(Object::toString).collect(Collectors.joining(",", "[", "]"));
System.out.println("CollectionBag的内容:" + result4);

Bag<Object> collectionBag2 = CollectionBag.collectionBag(treeBag);
String result5 = collectionBag2.stream().map(Object::toString).collect(Collectors.joining(",", "[", "]"));
System.out.println("CollectionBag2的内容:" + result5);

PredicatedBag & PredicatedSortedBag

PredicatedBag的构造器依赖一个现有Bag和一个Predicate,可以对加入进来的元素进行限制,比如不允许添加空元素。

/**
 * 创建PredicatedBag也依赖一个现有Bag,以及一个‘判断器’
 */
PredicatedBag<Object> predicatedBag = PredicatedBag.predicatedBag(collectionBag, Objects::nonNull);
String result6 = predicatedBag.stream().map(Object::toString).collect(Collectors.joining(",", "[", "]"));
System.out.println("predicatedBag的内容:" + result6);

SynchronizedBag & SynchronizedSortedBag

/**
 * SynchronizedBag同步的bag,使用Synchronized同步代码块实现同步。
 * 可以指定锁对象,如果不指定则锁this
 */
SynchronizedBag<Object> synchronizedBag = SynchronizedBag.synchronizedBag(collectionBag);
SynchronizedSortedBag<Object> synchronizedSortedBag = SynchronizedSortedBag.synchronizedSortedBag(treeBag);

TransformedBag

对原集合进行转化,一般不会用这个,java8提供的Stream API有一个Map方法,可以将结果映射。

  • transformingBag 方法,只会对后面add进来的元素进行转换,而对之前的初始化的不会转化
  • transformedBag方法,会对后加的以及一开始初始化的都进行转化
/**
 * TransformedBag
 */
Bag<Object> bag1 = TransformedBag.transformingBag(hashBag, Object::hashCode);
bag1.add("XX", 3);
String result8 = bag1.stream().map(Objects::toString).collect(Collectors.joining(",", "[", "]"));
System.out.println("TransformedBag.transformingBag " + result8);

Bag<Object> bag2 = TransformedBag.transformedBag(hashBag, Object::hashCode);
bag2.add("xx",3);
String result9 = bag2.stream().map(Objects::toString).collect(Collectors.joining(",", "[", "]"));
System.out.println("TransformedBag.transformingBag " + result9);

UnmodifiableBag

不可修改的Bag。

BagUtils

协助生成bag,其实调用的就是XXXBag.xxxBag()方法,每一个Bag类都会有一个静态方法,用于生成Bag。

/**
 * BagUtils  Bag工具类 协助生成Bag
 */
final Bag<Object> bag = BagUtils.collectionBag(new HashBag<>());
BidiMap

BidiMap - 提供双向映射,可通过键查找值,也可以通过值查找键

DualHashBidiMap

双重hashMap。其内封装了两个hashMap,bidimap的put()方法中key-value有任意重复的此条记录会被覆盖

/**
 * bidimap
 * - bidimap的put()方法中key-value有任意重复的此条记录会被覆盖
 */
@Test
public void testBidiMap() {

    final DualHashBidiMap<String, Integer> dualHashBidiMap = new DualHashBidiMap<>();
    dualHashBidiMap.put("a", 1);
    dualHashBidiMap.put("b", 2);
    dualHashBidiMap.put("c", 3);
    dualHashBidiMap.put("d", 3);
    dualHashBidiMap.put("e", 12);
    dualHashBidiMap.put("e", 123);

    System.out.println(dualHashBidiMap.get("a"));
    System.out.println(dualHashBidiMap.getKey(1));
    System.out.println(dualHashBidiMap.getKey(3));
    System.out.println(dualHashBidiMap.values());
    System.out.println(dualHashBidiMap.keySet());
}```

```bash
1
a
d
[1, 2, 3, 123]
[a, b, d, e]
erators

iterators提供了许多迭代包装类使我们很容易迭代集合,并且支持逆向迭代

ArrayItertor

数组迭代器,接收一个数组、迭代起始下标、迭代终止下标。

只接受迭代数组,因为next()方法会调用,本地静态方法Array.get(array,index) ArrayListIterator

接收一个数组,起始下标,终止下标。

ArrayIterator的拓展,支持正向迭代、也支持反向迭代。

public static native Object get(Object array, int index)
    throws IllegalArgumentException, ArrayIndexOutOfBoundsException;

简单使用

 /**
 * ArrayIterator 数组迭代器,接受一个数组、起始下标、终止下标
 */
Iterator<Object> arrayIterator1 = new ArrayIterator<>(Arrays.asList("1", "2", "3").toArray(),0,2);
while (arrayIterator1.hasNext()) {
    System.out.println(arrayIterator1.next());
}

ArrayListIterator

接收一个数组,起始下标,终止下标。

ArrayIterator的拓展,支持正向迭代、也支持反向迭代。

/**
 * ArrayListIterator 
 * 支持正向迭代、逆向迭代
 */
ArrayListIterator<Object> arrayListIterator2 = new ArrayListIterator<>(Arrays.asList("1", "2", "3","4", "5", "6").toArray(), 2, 6);
while (arrayListIterator2.hasNext()) {
    System.out.println(arrayListIterator2.next());
}
while (arrayListIterator2.hasPrevious()) {
    System.out.println(arrayListIterator2.previous());
}

BoundedIterator

有边界的迭代器,接收三个参数Iterator迭代器、offeset偏移量、max迭代数量。

如下表示从下标2开始、迭代2个元素,结果是 3、4

List<String> list = Arrays.asList("1", "2", "3", "4", "5");
BoundedIterator<String> boundedIterator = new BoundedIterator<>(list.iterator(), 2, 2);
while (boundedIterator.hasNext()) {
    System.out.println(boundedIterator.next());
}