Java 集合下

7、 Map 接口

public interface Map

HashMap

public class HashMap

private static void hashMap() {
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "Tom");
        map.put(2, "Jack");
        map.put(3, "Vince");
        map.put(4, "Bin");
        map.put(5, "Lily");
        System.out.println("size = " + map.size());
        System.out.println(map.get(1));

        // 遍历,一次性取出键和值
        Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
        for (Map.Entry e : entrySet) {
            System.out.println(e.getKey() + "->" + e.getValue());
        }
        // 先取出键
        Set<Integer> keys = map.keySet();
        for (Integer i : keys) {
            String value = map.get(i);
            System.out.println(i + "->" + value);
        }
        // 只取出值
        Collection<String> values = map.values();
        for (String value : values) {
            System.out.println(value);
        }

        // forEach
        map.forEach((Key, value) -> System.out.println(Key + "->" + value));
    }

HashMap 实现原理

  1. 基于哈希表(数组+链表+红黑树) 1.8JDK
  2. 初始大小为16
  3. 把Key对象通过hash() 方法计算hash值,然后用这个hash 值对数组长度取余数(默认16),来决定该对Key对象在数组中存储的位置,当这个位置有多个对象时,以链表结构存储,JDK1.8后,当链表长度大于8时,链表将转换为红黑树结构存储。这样的目的: 为了取值更快,存储的数据量越大,性能表现越明显
  4. 当数组的容量超过75%,那么表示该数组需要扩充,当前数组容量<<1,扩大1倍,扩充次数过多,会影响性能,每次扩充表示哈希表重新散列(重新计算每个对象的存储位置),我们在开发中尽量要减少扩充次数带来的性能问题。
  5. 线程不安全

default load factor( 0.75):

Hashtable

public class Hashtable

public static void hashtable(){
        Map<String,String> table = new Hashtable<>();
        table.put("one","Lily");
        table.put("two","Tom");
        table.put("three","Bin");

        table.forEach((key,value) -> System.out.println(key+"->"+value));


    }

LinkedHashMap

public class LinkedHashMap

public static void linkedHashMap(){
        Map<String,String> table = new LinkedHashMap<>();
        table.put("one","Lily");
        table.put("two","Tom");
        table.put("three","Bin");

        table.forEach((key,value) -> System.out.println(key+"->"+value));
    }

TreeMap

public class TreeMap

JDK1.8 新加入的方法

getOrDefault: get 方法默认如果key没有找到,那么会得到null

putIfAbsent :map 的put方法,如果key 已经存在了,value 会被覆盖,(源码,先get,如果value是null,在put)

remvoe(Object key, Object value); 键和值都匹配才会被删除

replace(Key, oldvalue, newvalue)

        map.compute(1,(k,v)->v+"1");
        map.computeIfAbsent(6,(val)->val+"test");
        map.merge(1,"888",(old,newv)->old.concat(newv));

Collections 工具类

排序操作

reverse(List list) 反转指定List 集合中的元素

shuffle(List list) 对List 中的元素进行随机排序

sort(List list) 对List 里的元素根据自然升序排序

sort(List list, Comparator c) 自定义比较器进行排序

swap(List list, int i, int j) 指定List 集合中i处元素和j处元素交换

rotate(List list, int distance) 将所有元素向右移位指定长度,如果distance等于size那么结果不变

查找和替换

binarySearch(List list, Object key) 使用二分搜索法,以获得指定对象在list 中的索引,前提是集合已经排序
max(Collection coll) 返回最大元素
max(Collection coll, Comparator comp) 根据自定义比较器,返回最大元素
min(Collection coll) 返回最小元素
min(Collection coll, Comparator comp) 根据自定义比较器,返回最小元素
fill(List list, Object o) 使用指定对象填充
frequency(Collection Object, o) 返回指定集合中指定对象的出现次数
replaceAll(List list, Object old, Object new) 替换

同步控制

Collections 工具类中提供了多个synchronized方法,该方法返回指定集合对象对应的同步对象,从而解决多线程并发访问集合时线程的安全问题。HashSet、ArrayList、HashMap都是线程不安全的,如果需要考虑同步,则使用这些方法,这些方法右:synchronizedSet、 synchronizedSortedSet、 synchronizedList、synchronizedMap、synchronizedSortedMap

特别需要指出的是,在使用迭代方法遍历集合时需要手工同步返回的集合

设置不可变集合

Collections 有三类方法返回一个不可变集合

empty() 返回一个空的不可变的集合对象

singleton() 返回一个只包含指定对象的,不可变集合对象

unmodifiable() 返回指定集合对象的不可变视图

其他

disjoint 如果两个指定collection中没有相同的元素,则返回true

addAll 一种方便的方式,将所有指定元素添加到指定的collection 中

Comparator 返回一个比较器,它强行反转指定比较器的顺序。如果指定比较器为null,则此方法等同于reverseOrder (换句话说,它返回一个比较器,该比较器将强行反转实现COmparable接口那些对象,collection

上的自然顺序)

Optional 容器类

这是一个可以为null 的容器对象,如果值存在则isPresent() 方法会返回true, 调用get()方法会返回该对象

of: 为非null的值创建一个Optional

ofNullable: 为指定的值创建一个Optional, 如果指定的值为null, 则返回一个空的Optional

isPresent: 如果值存在返回true, 否则返回false

get 如果值存在返回true, 否则返回false

ifPresent: 如果Optional 实例有值则为其调用consumer, 否则不做处理

orElse 如果有值则将其返回,否则返回指定的其他值

orElseGet: 和orElse 方法类似,区别在于得到的默认值,orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier 接口的实现用来生成默认值

orElseThrow: 如果有值则将其返回,否则抛出supplier 接口创建的异常

map: 如果有值,则对其执行调用mapping 函数得到返回值,如果返回值不为null, 则创建包含mapping 返回值的optional 作为map方法返回值,否则返回空optional

flatMap: 如果有值,为其执行mapping 函数返回Optional 类型返回值,否则返回空Optional。 flatMap与map方法类似,区别在于flatMap 中的mapper 返回值必须是Optional。 调用结束时,flatMap 不会对结果用Optional 封装

filter: 如果有值并满足断言条件返回包含该值的optional, 否则返回空Optional

Queue 和Deque

队列(queue)是一种特殊的线性表,是一种先进先出的数据结构,它允许在表的前端进行删除操作,而在表的后端(rear)进行插入操作。进行插入操作的端称为队尾。进行删除操作的端称为队头,队列中没有元素时,称为空队列。LinkedList 实现了Deque 接口

addFirst 是在前端进行插入操作, 使用poll 操作取出前端的值

Deque

peek 是查询first, poll 是移除first

getFirst() 就是得到最先add 进入的值

迭代器设计模式

提供一个方法按顺序遍历一个集合内的元素,而又不需要暴露该对象的内部表示

  1. 访问一个聚合的对象,而不需要暴露对象的内部表示
  2. 支持对聚合对象的多种遍历
  3. 对遍历不同的对象,提供统一的接口

guava 对集合的支持

Guava 工程包含了若干个被 google 的java 项目广泛依赖的核心库,例如集合(collections), 缓存(caching),原生类型支持(primitives support), 并发库(concurrency libraries), 通用注解(common annotations)、 字符串处理(string processing), I/O等等,

1、 只读设置

@Test
    public void testGuava1() {
        System.out.println("test guava");
        List<String> list1 = Arrays.asList("jack","tom","lily","bin");
//        list.add("vicne");
        List<String> list2 = new ArrayList<>();
        list2.add("1");
        list2.add("2");
        List<String> readList = Collections.unmodifiableList(list2);
//        readList.add("vince");

        ImmutableList<String> iList =  ImmutableList.of("jack","tom","lily");
//        iList.add("vince");
    }

2、函数式编程: 过滤器

@Test
    public void testGuava2(){
        List<String> list = Lists.newArrayList("java","php","jack");
        Collection<String> res =  Collections2.filter(list,(e)->e.startsWith("j"));
        res.forEach(System.out::println);
    }

3、函数式编程:转换

    @Test
    public void testGuava3(){
        Set<Long> timeSet = Sets.newHashSet(20121212L,20170520L,20120403L);
        Collection<String> timeCollect = Collections2.
                transform(timeSet,(e)-> new SimpleDateFormat("yyyy-mm-dd").format(e));
        timeCollect.forEach(System.out::println);
    }

    @Test
    public void testGuava4(){
        List<String> list = Lists.newArrayList("java","php","jack","h5");
        Function<String,String> f1 = new Function<String,String>(){

            @Override
            public String apply(String t) {
                return t.length()>4?t.substring(0,4):t;
            }
        };
        Function<String,String> f2 = new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.toUpperCase();
            }
        };
        Function<String,String> f = Functions.compose(f1,f2);
        Collection<String> coll = Collections2.transform(list,f);
        coll.forEach(System.out::println);
    }

4、组合式函数编程

@Test
public void testGuava4() {
    List<String> list = Lists.newArrayList("java", "php", "jack", "h5");
    Function<String, String> f1 = new Function<String, String>() {

        @Override
        public String apply(String t) {
            return t.length() > 4 ? t.substring(0, 4) : t;
        }
    };
    Function<String, String> f2 = new Function<String, String>() {
        @Override
        public String apply(String s) {
            return s.toUpperCase();
        }
    };
    Function<String, String> f = Functions.compose(f1, f2);
    Collection<String> coll = Collections2.transform(list, f);
    coll.forEach(System.out::println);
}

5、加入约束:非空、长度验证

14版本之后移除了Constraint 类

6、 集合操作: 交集、差集、并集

@Test
public void testGuava6() {
    Set<Integer> set1 = Sets.newHashSet(1, 2, 3);
    Set<Integer> set2 = Sets.newHashSet(2, 3, 4);
    // 交集
    Sets.SetView<Integer> v1 = Sets.intersection(set1, set2);
    v1.forEach(s -> System.out.print(s + " "));
    System.out.println();

    // 差集
    Sets.SetView<Integer> v2 = Sets.difference(set1, set2);
    v1.forEach(s -> System.out.print(s + " "));
    System.out.println();

    // 并集
    Sets.SetView<Integer> v3 = Sets.union(set1, set2);
    v3.forEach(s -> System.out.print(s + " "));
    System.out.println();
}

7、Multiset:无序可重复

@Test
public void testGuava7() {
    String s = "good good study day day up";
    String[] ss = s.split(" ");
    HashMultiset<String> set = HashMultiset.create();
    for (String str : ss) {
        set.add(str);
    }
    Set<String> set2 = set.elementSet();

    for (String str : set2) {
        System.out.println(str + ":" + set.count(str));
    }
}

8、Multimap key可以重复

@Test
public void testGuava8() {
    Map<String, String> map = new HashMap<>();
    map.put("Java从入门到精通", "bin");
    map.put("Android从入门到精通", "bin");
    map.put("PHP从入门到精通", "jack");
    map.put("笑看人生", "vince");

    Multimap<String, String> mmap = ArrayListMultimap.create();
    Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();

    while (iter.hasNext()) {
        Map.Entry<String, String> entry = iter.next();
        mmap.put(entry.getValue(), entry.getKey());
    }
    Set<String> keySet = mmap.keySet();
    for (String key : keySet) {
        System.out.println(key + " " + mmap.get(key).toString());
    }
}

9、 BiMap: 双向Map(bidirectional Map)键与值不能重复

@Test
public void testGuava9() {
    BiMap<String, String> map = HashBiMap.create();
    map.put("finally_test", "18800208123");
    map.put("bin", "18800208234");
    System.out.println(map.inverse().get("18800208123"));

    for (Map.Entry e : map.entrySet()) {
        System.out.println(e.getKey() + " " + e.getValue());
    }
}

10、 双键的Map table rowKey+columnKey+value

@Test
public void testGuava10() {
    Table<String, String, Integer> table = HashBasedTable.create();
    table.put("jack", "java", 80);
    table.put("tom", "php", 70);
    table.put("bin", "java", 59);
    table.put("lily", "ui", 98);
    Set<Table.Cell<String, String, Integer>> cells = table.cellSet();
    for (Table.Cell c : cells) {
        System.out.println(c.getRowKey() + " " + c.getColumnKey() + " " + c.getValue());
    }
}

猜你喜欢

转载自blog.csdn.net/LEIQINGQI/article/details/82120134