java代码之美(2)

guava 复写Object常用方法

       Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,这个库提供用于集合,缓存,支持原语,并发性,常见注解,字符串处理,I/O和验证的实用方法。

这些高质量的 API 可以使你的Java代码更加优雅,更加简洁,让你工作更加轻松愉悦。 

一、概述

      在Java中Object类是所有类的父类,其中有几个需要override的方法比如equals,hashCode和toString等方法。每次写这几个方法都要做很多重复性的判断,

很多类库提供了覆写这几个方法的工具类, Guava也提供了类似的方式。下面我们来看看Guava中这几个方法简单使用。

     Guava中Objects类提供了很多和Object类作用相同、效率更高的方法可供使用:

1、equal方法

       使用Obejct的equals方法进行相等判断,例如:test.equals("test");如果test为null,则会发生NullPointerException,Objects的equal方法可以帮助你

避免NullPointerException,它的判断逻辑是这样的:return a == b || (a!=null&& a.equals(b));所以,可以很放心的使用,Objects.equal(test,"test")

当然在JDK7中也提供了同样判断逻辑的方法:Objects.equals(test,"test");

复制代码
public class ObjectTest {
    
    @Test
    public void equalTest() {
        System.out.println(Objects.equal("a", "a"));
        System.out.println(Objects.equal(null, "a")); 
        System.out.println(Objects.equal("a", null)); 
        System.out.println(Objects.equal(null, null));
    }
}
/**输出结果
 * true
 * false
 * false
 * true
 */
复制代码

 2、hashCode方法

对于hashCode首先要明白两点:

      1、如果equals()判断两个对象相等,那么它们的hashCode()方法一定返回同样的值。

  2、并没有强制要求如果equals()判断两个对象不相等,它们的hashCode可以相同也可以不同。

Guava提供给我们了一个更加简单的方法--Objects.hashCode(Object ...), 这是个可变参数的方法,参数列表可以是任意数量,所以可以像这样

使用Objects.hashCode(field1, field2, ...,fieldn)。非常方便和简洁。

复制代码
import org.junit.Test;
import com.google.common.base.Objects;

public class ObjectTest {    
    @Test
    public void hashcodeTest() {
        System.out.println(Objects.hashCode("a"));
        System.out.println(Objects.hashCode("a"));
        System.out.println(Objects.hashCode("a","b"));
        System.out.println(Objects.hashCode("b","a"));
        System.out.println(Objects.hashCode("a","b","c"));
        
        Person person=new Person("peida",23);
        System.out.println(Objects.hashCode(person));
        System.out.println(Objects.hashCode(person));
    }
}

class Person {
    public String name;
    public int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
复制代码
复制代码
//输出结果
128
4066
4096
126145
19313256
19313256
复制代码

3、toStringHelper()方法

       因为每个类都直接或间接地继承自Object,因此每个类都有toString()方法。这个方法是用得最多的, 覆写得最多, 一个好的toString方法对于调试来说是非常重要的,

但是写起来确实很不爽。Guava也提供了toString()方法。

通过toStringHelper方法来输出你需要输出的属性字段

复制代码
import org.junit.Test;
import com.google.common.base.Objects;

public class ObjectTest {
    
    @Test
    public void toStringTest() {
         //this代表当前类,这里只输出x一个属性字段
        System.out.println(Objects.toStringHelper(this).add("x", 1).toString());

        //代表输出对象为Person对象  
System.out.println(Objects.toStringHelper(Person.class).add("x", 1).toString()); //add可以叠加 Person person=new Person("peida",23); String result = Objects.toStringHelper(Person.class).add("name", person.name).add("age", person.age).toString(); System.out.print(result); } } class Person { public String name; public int age; Person(String name, int age) { this.name = name; this.age = age; } } //============输出=============== ObjectTest{x=1} Person{x=1} Person{name=peida, age=23}
复制代码

4、firstNonNull方法

  Object的firstNonNull方法可以根据传入的两个参数来返回一个非Null的参数,Guava现在推荐使用MoreObjects.firstNonNull(T first,T second)替代它。

复制代码
import com.google.common.base.MoreObjects;

public class TestFilter {

    public static void main(String[] args) {
      //name不为空
        String  name="张三";
        String nann=  MoreObjects.firstNonNull(name, "哈哈");
        System.out.println(nann);

      //sex为null
        String   sex=null;
        String   sexx=  MoreObjects.firstNonNull(sex, "哈哈");
        System.out.println(sexx);

    }
    /*
     *运行结果:
     *  张三
     *  哈哈
     */
}
复制代码

在实际开发中,Objects.equal(test,"test")和MoreObjects.firstNonNull(T first,T second)在许多实际场合还是非常有帮助的。

Immutable(不可变)集合

一、概述

      guava是google的一个库,弥补了java语言的很多方面的不足,很多在java8中已有实现,暂时不展开。Collections是jdk提供的一个工具类。

      Guava中不可变对象和Collections工具类的unmodifiableSet/List/Map/etc的区别:

当Collections创建的不可变集合的wrapper类改变的时候,不可变集合也会改变,而Guava的Immutable集合保证确实是不可变的。

1、JDK中实现immutable集合

 在JDK中提供了Collections.unmodifiableXXX系列方法来实现不可变集合, 但是存在一些问题,下面我们先看一个具体实例:

复制代码
public class ImmutableTest {

    @Test
    public void testJDKImmutable(){
        List<String> list=new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");

        //通过list创建一个不可变的unmodifiableList集合
        List<String> unmodifiableList=Collections.unmodifiableList(list);
        System.out.println(unmodifiableList);

        //通过list添加元素
        list.add("ddd");
        System.out.println("往list添加一个元素:"+list);
        System.out.println("通过list添加元素之后的unmodifiableList:"+unmodifiableList);

        //通过unmodifiableList添加元素
        unmodifiableList.add("eee");
        System.out.println("往unmodifiableList添加一个元素:"+unmodifiableList);

    }
}
复制代码

运行结果:

通过运行结果我们可以看出:虽然unmodifiableList不可以直接添加元素,但是我的list是可以添加元素的,而list的改变也会使unmodifiableList改变。

所以说Collections.unmodifiableList实现的不是真正的不可变集合。

 2、Guava的immutable集合

      Guava提供了对JDK里标准集合类里的immutable版本的简单方便的实现,以及Guava自己的一些专门集合类的immutable实现。当你不希望修改一个集合类,

或者想做一个常量集合类的时候,使用immutable集合类就是一个最佳的编程实践。 

注意:每个Guava immutable集合类的实现都拒绝null值。我们做过对Google内部代码的全面的调查,并且发现只有5%的情况下集合类允许null值,而95%的情况下

都拒绝null值。万一你真的需要能接受null值的集合类,你可以考虑用Collections.unmodifiableXXX。

immutable集合可以有以下几种方式来创建:

  1、用copyOf方法, 譬如, ImmutableSet.copyOf(set)

  2、使用of方法,譬如,ImmutableSet.of("a", "b", "c")或者ImmutableMap.of("a", 1, "b", 2)

  3、使用Builder类

举例:

复制代码
 @Test
    public void testGuavaImmutable(){

        List<String> list=new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");

        ImmutableList<String> imlist=ImmutableList.copyOf(list);
        System.out.println("imlist:"+imlist);

        ImmutableList<String> imOflist=ImmutableList.of("peida","jerry","harry");
        System.out.println("imOflist:"+imOflist);

        ImmutableSortedSet<String> imSortList=ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");
        System.out.println("imSortList:"+imSortList);

        list.add("baby");
        //关键看这里是否imlist也添加新元素了
        System.out.println("list添加新元素之后看imlist:"+imlist);

        ImmutableSet<Color> imColorSet =
                ImmutableSet.<Color>builder()
                        .add(new Color(0, 255, 255))
                        .add(new Color(0, 191, 255))
                        .build();

        System.out.println("imColorSet:"+imColorSet);
    }
复制代码

运行结果:发现imlist并未改变。

对于排序的集合来说有例外,因为元素的顺序在构建集合的时候就被固定下来了。譬如,ImmutableSet.of("a", "b", "c", "a", "d", "b"),对于这个集合的遍历顺序来说就是"a", "b", "c", "d"。

更智能的copyOf

copyOf方法比你想象的要智能,ImmutableXXX.copyOf会在合适的情况下避免拷贝元素的操作-先忽略具体的细节,但是它的实现一般都是很“智能”的。譬如:

复制代码
  @Test
        public void testCotyOf(){
            ImmutableSet<String> imSet=ImmutableSet.of("peida","jerry","harry","lisa");
            System.out.println("imSet:"+imSet);

            //set直接转list
            ImmutableList<String> imlist=ImmutableList.copyOf(imSet);
            System.out.println("imlist:"+imlist);

            //list直接转SortedSet
            ImmutableSortedSet<String> imSortSet=ImmutableSortedSet.copyOf(imSet);
            System.out.println("imSortSet:"+imSortSet);

            List<String> list=new ArrayList<String>();
            for(int i=0;i<=10;i++){
                list.add(i+"x");
            }
            System.out.println("list:"+list);

            //截取集合部分元素
            ImmutableList<String> imInfolist=ImmutableList.copyOf(list.subList(2, 8));
            System.out.println("imInfolist:"+imInfolist);
        }
复制代码

 运行结果

Guava集合和不可变对应关系

可变集合类型 可变集合源:JDK or Guava? Guava不可变集合
Collection JDK ImmutableCollection
List JDK ImmutableList
Set JDK ImmutableSet
SortedSet/NavigableSet JDK ImmutableSortedSet
Map JDK ImmutableMap
SortedMap JDK ImmutableSortedMap
Multiset Guava ImmutableMultiset
SortedMultiset Guava ImmutableSortedMultiset
Multimap Guava ImmutableMultimap
ListMultimap Guava ImmutableListMultimap
SetMultimap Guava ImmutableSetMultimap
BiMap Guava ImmutableBiMap
ClassToInstanceMap Guava ImmutableClassToInstanceMap
Table Guava ImmutableTable

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

guava之Multiset

一、概述

       Guava提供了一个新集合类型Multiset,它可以多次添加相等的元素,且和元素顺序无关。Multiset继承于JDK的Cllection接口,而不是Set接口。它和set最大的区别就是

它可以对相同元素做一个计数的功能,普通的 Set 就像这样 :[car, ship, bike],而 Multiset 会是这样 : [car x 2, ship x 6, bike x 3]Multiset有一个有用的功能,

就是跟踪每种对象的数量,所以你可以用来进行数字统计。每存放一个相同元素,那么该元素的count就加1。

譬如一个 List 里面有各种字符串,然后你要统计每个字符串在 List 里面出现的次数,这个用Multiset就能够快速实现。

1、举例说明

复制代码
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;

public class MultisetTest {

    public static void main(String[] args) {

        String str = "张三 李四 李四 王五 王五 王五";
        String[] strArr = str.split(" ");

        List<String> words = new ArrayList<String>(Arrays.asList(strArr));

        //创建一个HashMultiset集合,并将words集合数据放入
        Multiset<String> wordMultiset = HashMultiset.create();
        wordMultiset.addAll(words);

        //将不同的元素放在一个集合set中
        for (String key : wordMultiset.elementSet()) {
            //查看指定元素的个数
            System.out.println(key + "-->" + wordMultiset.count(key));
        }

        System.out.println("---------向集合中添加元素----------");
        //向集合中添加元素
        wordMultiset.add("李四");
        for (String key : wordMultiset.elementSet()) {
            System.out.println(key + "-->" + wordMultiset.count(key));
        }

        System.out.println("-------向集合中添加若干个元素------");
        //向集合中添加若干个元素
        wordMultiset.add("赵六", 10);
        for (String key : wordMultiset.elementSet()) {
            System.out.println(key + "-->" + wordMultiset.count(key));
        }

        System.out.println("--------向集合中移出一个元素------");
        //向集合中移出一个元素
        wordMultiset.remove("张三");
        for (String key : wordMultiset.elementSet()) {
            System.out.println(key + "-->" + wordMultiset.count(key));
        }

        System.out.println("------向集合中移出若干个元素------");
        //向集合中移出若干个元素,如果元素的个数小于要移除的个数,则会把该元素移除光
        wordMultiset.remove("赵六",5);
        for (String key : wordMultiset.elementSet()) {
            System.out.println(key + "-->" + wordMultiset.count(key));
        }


        System.out.println("-----设定某一个元素的重复次数-----");
        //设定某一个元素的重复次数
        wordMultiset.setCount("张三", 10);
        for (String key : wordMultiset.elementSet()) {
            System.out.println(key + "-->" + wordMultiset.count(key));
        }

        System.out.println("-----设置复合元素的个数设为新的重复次数-----");
        //设置复合元素的个数设为新的重复次数(条件是第二个参数的数量要是实际数量一致,否则无效)
        wordMultiset.setCount("and", 1,0);
        for (String key : wordMultiset.elementSet()) {
            System.out.println(key + "-->" + wordMultiset.count(key));
        }

        System.out.println("-------删除给定集合中的元素------");
        //删除给定集合中的元素
        wordMultiset.removeAll(words);
        for (String key : wordMultiset.elementSet()) {
            System.out.println(key + "-->" + wordMultiset.count(key));
        }
    }
} 
复制代码

主要看运行结果:

根据运行结果我们得到:

  (1)它把把list放入HashMultiset中,就成了key还是list的属性,value就是重复数的一个计数。

  (2)每添加一个相同元素,计数+1。

  (3)可以添加和移除计数的值。

 2、Multiset主要方法介绍

  • add(E element) :向其中添加单个元素

  • add(E element,int occurrences) : 向其中添加指定个数的元素

  • count(Object element) : 返回给定参数元素的个数

  • remove(E element) : 移除一个元素,其count值 会响应减少

  • remove(E element,int occurrences): 移除相应个数的元素

  • elementSet() : 将不同的元素放入一个Set中

  • entrySet(): 类似与Map.entrySet 返回Set<Multiset.Entry>。包含的Entry支持使用getElement()和getCount()

  • setCount(E element ,int count): 设定某一个元素的重复次数

  • setCount(E element,int oldCount,int newCount): 将符合原有重复个数的元素修改为新的重复次数

  • retainAll(Collection c) : 保留出现在给定集合参数的所有的元素

  • removeAll(Collectionc) : 去除出现给给定集合参数的所有的元素

 3、常用的实现了Multiset 接口的类

      1、HashMultiset: 元素存放于 HashMap

     2、LinkedHashMultiset: 元素存放于 LinkedHashMap,即元素的排列顺序由第一次放入的顺序决定

     3、TreeMultiset:元素被排序存放于TreeMap

     4、EnumMultiset: 元素必须是 enum 类型

     5、ImmutableMultiset: 不可修改的 Mutiset

4、Multiset与Map<E, Integer>区别

实际开发中我们也可以利用Map<E, Integer>来实现计数功能,但它和Multiset还是有很大区别的,首先Multiset也不是Map<E, Integer>类型的结构,区别如下:

    1、Multiset中的元素出现的次数只能为正数,前面说了原因。如果E的出现次数为0,那么E将不出现在multiset中,是不能在elementSet()和entrySet()的视图中;

    2、multiset.size()返回这个集合的大小,相当于在multiset中元素的出现的总数。如果想得到multiset中不同元素出现的总数,可以利用elementSet().size()来实现;

    3、multiset.iterator()可以遍历multiset中的所有元素,所以iteration遍历的次数就等于multiset.size();

    4、Multiset支持添加、删除元素,设置元素出现的次数;setCount(elem, 0)相当于移除elem的所有元素;

    5、multiset.count(elem)方法中的elem如果没有出现在Multiset中,那么它的返回值永远都是0。

guava之multimap

上一篇讲到Multiset它可以对存入相同元素做一个计数的功能,那multimap呢?

一、概述

1、基本介绍和案例说明

multimap和MultiSet的继承结果很相似,只不过在上层的接口是Multimap不是Multiset。

Multimap的特点其实就是可以包含有几个重复Key的value,你可以put进入多个不同value但是相同的key,但是又不是让后面覆盖前面的内容。

它的业务场景:当你需要构造像Map<K, List<V>>或者Map<K, Set<V>>这样比较复杂的集合类型的数据结构,来做相应的业务逻辑处理。那Multimap在合适不过。

举例

复制代码
        @Test
        public void testMultimap(){
        HashMultimap<Integer, Integer> map = HashMultimap.create();
        map.put(1, 2);
        map.put(1, 3);
        map.put(1, 2);
        map.put(2, 3);
        map.put(4, 2);
        map.put(4, 3);
        map.put(4, 2);
        map.put(4, 3);
        System.out.println(map.toString());
    }
}
/*输出结果:
 *{1=[2, 3], 2=[3], 4=[2, 3]}
 */
复制代码

其实它会把相同key和value的值给覆盖起来,但是相同的key又可以保留不同的value。因为它的entry的实现是一个set,set会对相同的Entry<K,V>进行去重,所以会有这种情况。 

2、实际开发场景及常用方法

 (1)根据业务需要对下面的list数据根据name字段来进行分组:

复制代码
[
    {
        "date":"2018-01-31",
        "name":"wuzhong",
        "socre":0.8
    },
    {
        "date":"2018-01-30",
        "name":"wuzhong",
        "socre":0.9
    },
    {
        "date":"2018-01-31",
        "name":"wuzhong2",
        "socre":0.8
    }
]
复制代码

传统做法

复制代码
//Item就是封装的对象
Map<String,List<Item>> map = new HashMap<>();
for (Item item : list){
  List<Item> tmp = map.get(item.getName());
  if (null == tmp){
      tmp = new ArrayList<>();
      map.put(item.getName(),tmp);
  }
  tmp.add(item);
}
复制代码

很简单, 但是代码量有点多,特别是需要判断List为null并初始化。

再用guava实现上述的功能:

Multimap<String,Item> multiMap = ArrayListMultimap.create();
for (Item item : list){
    multiMap.put(item.getName(),item);
}

代码量直接减少了一半,这就是实际开发中它发挥的作用。

(2)再举一例子了解常用方法

复制代码
public class MultimapTest {


        public static void main(String args[]){

              Multimap<String,String> multimap = ArrayListMultimap.create();

            multimap.put("lower", "a");
            multimap.put("lower", "b");
            multimap.put("lower", "c");

            multimap.put("upper", "A");
            multimap.put("upper", "B");

            List<String> lowerList = (List<String>)multimap.get("lower");
            //输出key为lower的list集合
            System.out.println("输出key为lower的list集合=========");
            System.out.println(lowerList.toString());
            lowerList.add("f");
            System.out.println(lowerList.toString());


            Map<String, Collection<String>> map = multimap.asMap();
            System.out.println("把Multimap转为一个map============");
            for (Map.Entry<String,  Collection<String>> entry : map.entrySet()) {
                String key = entry.getKey();
                Collection<String> value =  multimap.get(key);
                System.out.println(key + ":" + value);
            }

            System.out.println("获得所有Multimap的key值==========");
            Set<String> keys =  multimap.keySet();
            for(String key:keys){
                System.out.println(key);
            }

            System.out.println("输出Multimap所有的value值========");
            Collection<String> values = multimap.values();
            System.out.println(values);
        }
}
/**输出结果:
 *输出key为lower的list集合=========
 * [a, b, c]
 * [a, b, c, f]
 * 把Multimap转为一个map============
 * lower:[a, b, c, f]
 * upper:[A, B]
 * 获得所有Multimap的key值==========
 * lower
 * upper
 * 输出Multimap所有的value值========
 * [a, b, c, f, A, B]
  */
复制代码

4、Multimap的实现类

  Multimap提供了丰富的实现,所以你可以用它来替代程序里的Map<K, Collection<V>>,具体的实现如下:

  Implementation            Keys 的行为类似          Values的行为类似

  ArrayListMultimap         HashMap                     ArrayList

  HashMultimap               HashMap                     HashSet

  LinkedListMultimap        LinkedHashMap*              LinkedList*

  LinkedHashMultimap      LinkedHashMap                LinkedHashSet

  TreeMultimap                TreeMap                          TreeSet

  ImmutableListMultimap  ImmutableMap                 ImmutableList

  ImmutableSetMultimap  ImmutableMap                 ImmutableSet  

  以上这些实现,除了immutable的实现都支持null的键和值。

  1、LinkedListMultimap.entries()能维持迭代时的顺序。

  2、LinkedHashMultimap维持插入的顺序,以及键的插入顺序。

guava之Bimap

 bimap的作用很清晰:它是一个一一映射,可以通过key得到value,也可以通过value得到key。

一、概述

1、bimap和普通HashMap区别

(1)在Java集合类库中的Map,它的特点是存放的键(Key)是唯一的,而值(Value)可以不唯一,而

        bimap要求key和value都唯一,如果key不唯一则覆盖key,如果value不唯一则直接报错。

2、案例展示

复制代码
public class bimapTest {
        public static void main(String args[]){

            //双向map
            BiMap<Integer,String> biMap=HashBiMap.create();
            biMap.put(1,"张三");
            biMap.put(2,"李四");
            biMap.put(3,"王五");
            biMap.put(4,"赵六");
            biMap.put(5,"李七");
            biMap.put(4,"小小");

            //通过key值得到value值(注意key里面的类型根据泛行
            String value= biMap.get(1);
            System.out.println("id为1的value值 --"+value);

            //通过value值得到key值
            int key= biMap.inverse().get("张三");
            System.out.println("张三key值 --"+key);

            //通过key值重复,那么vakue值会被覆盖。
            String valuename= biMap.get(4);
            System.out.println("id为4的value值 --"+valuename);
        }
}
/*运行结果:
 *id为1的value值 --张三
 *张三key值 --1
 *id为4的value值 --小小
 */
复制代码

如果value值重复,则运行直接报错如下:

复制代码
  biMap.put(6,"小小");
            /**后台直接报错
             * Exception in thread "main" java.lang.IllegalArgumentException: value already present: 小小
             *     at com.google.common.collect.HashBiMap.put(HashBiMap.java:285)
             *     at com.google.common.collect.HashBiMap.put(HashBiMap.java:260)
             *     at com.jincou.stream.study.bimapTest.main(bimapTest.java:40)
             */
复制代码

如果你想value也发生覆盖key值,那么可以:

复制代码
   // inverse方法会返回一个反转的BiMap,但是注意这个反转的map不是新的map对象,它实现了一种视图关联,这样你对于反转后的map的所有操作都会影响原先的map对象。
       biMap.forcePut(6,"小小");
       int key6= biMap.inverse().get("小小");
       System.out.println("小小key值 --"+key6);
/**后台输出(已经把:biMap.put(4,"小小"覆盖) * * 小小key值 --6 */
复制代码

3、Bimap实现类

BiMap的常用实现有:

    1、HashBiMap: key 集合与 value 集合都有 HashMap 实现

    2、EnumBiMap: key 与 value 都必须是 enum 类型

    3、ImmutableBiMap: 不可修改的 BiMap

guava字符串工具

在java开发过程中对字符串的处理是非常频繁的,google的guava工具对字符串的一些处理进行优化,使我们开发过程中让自己的代码看去更加美观,清爽。

一、Joiner

      根据给定的分隔符把字符串连接到一起。MapJoiner 执行相同的操作,但是针对 Map 的 key 和 value。

     分析源码可知:该类构造方法被private修身,无法直接通过new实现,通过调用on传如分隔符来得到实例。 

案例

复制代码
public class JoinerTest {

    public static void main(String args[]){

     //1、将list字符串集合,以,形式转为字符串
        List<String> list =new ArrayList<String>();
        list.add("xx");
        list.add("zz");
        list.add("dd");

        //Joiner.on(",")获得Joiner实例对象
        Joiner joiner =  Joiner.on(",");
        //joiner.join(list)传入操作的集合,并转成字符串格式
        System.out.println(joiner.join(list));
        //输出结果:xx,zz,dd

     //2、将Iterator<T>列表,转为字符串
        Iterator<String> it=list.iterator();
        String  str=Joiner.on("|").join(it);
        System.out.println(str);
        //输出结果:xx|zz|dd

     //3、连接多个字符串
        String str1=Joiner.on(",").join("小小","爸爸","妈妈","爷爷","奶奶");
        System.out.println(str1);
        //输出:小小,爸爸,妈妈,爷爷,奶奶

     //4、连接字符串与列表
        StringBuilder builder=new StringBuilder("小小最乖");
        //返回StringBuilder类型
        StringBuilder str2=Joiner.on(",").appendTo(builder,list);
        System.out.println(str2);
        //输出:小小最乖xx,zz,dd

     //5、跳过null值连接
        list.add(null);
        list.add("小小");
        //skipNulls()代表去除null
        String str3=Joiner.on(",").skipNulls().join(list);
        System.out.println(str3);
        //输出:xx,zz,dd,小小

     //6、替换null值进行连接
        String str4=Joiner.on(",").useForNull("空").join(list);
        System.out.println(str4);
        //输出:xx,zz,dd,空,小小

     //7、Map的键值对打印出来
        Map<String, String> map = new HashMap<>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");
        Joiner.MapJoiner mapJoiner = Joiner.on(",").withKeyValueSeparator("=");
        System.out.println(mapJoiner.join(map));
        //输出:key1=value1,key2=value2,key3=value3     
    //8、一步将字符串转为List<Long>集合(前面先转为list<String>,后面用java8特性将List<String>转为List<Long>)
List<Long> list=Splitter.on("#").splitToList("111#222#333").stream().mapToLong(str->Long.parseLong(str)).boxed().distinct().collect(Collectors.toList());
} }
复制代码

Joiner在实际开发中,用处还是蛮大的。

 

二、Splitter

主要功能是拆分字符串为集合 Map等。 通过分析源码可知,该工具类是通过on函数传入拆分字符得到实例。

案例:

复制代码
public class SplitterTest {

    public static void main(String args[]){

     //1、拆分字符串为List集合
        String str="小小,妈妈,爸爸,爷爷,奶奶";
        Splitter splitter =Splitter.on(",");
        List<String> list=splitter.splitToList(str);
        System.out.println(list);
        //输出:[小小, 妈妈, 爸爸, 爷爷, 奶奶]

     //2、忽略空字符
        String str1="a,b,c,d,,f,g";
        //omitEmptyStrings()代表去除空字符串
        List<String> list1=Splitter.on(",").omitEmptyStrings().splitToList(str1);
        System.out.println(list1);
        //输出:[a, b, c, d, f, g]

     //3、忽略空字符且去除字符串前后空格
        String str2="a,b,c,d,,f,  g  ";
        List<String> list2=Splitter.on(",").omitEmptyStrings().trimResults().splitToList(str2);
        System.out.println(list2);
        //输出:[a, b, c, d, f, g]
    }
}
复制代码

 

 

三、Strings

案例

复制代码
public class StringsTest {

    public static void main(String args[]){

     //1、补右全(Strings.padEnd方法)
        String a="12345";
        String b=Strings.padEnd(a, 10, 'x');
        System.out.println(b);
        //输出:12345xxxxx

     //2、补左全(Strings.padStart)
        String c=Strings.padStart(a, 10, 'x');
        System.out.println(c);
        //输出:xxxxx12345

     //3、校验空值和null
        String d="";
        String f=null;
        boolean e=Strings.isNullOrEmpty(d);
        boolean h=Strings.isNullOrEmpty(f);
        System.out.println(e);
        System.out.println(h);
        //输出:true,true

     //4、如果为null 转为""
        String m=null;
        String n=Strings.nullToEmpty(m);
        System.out.println(n);
        //输出:

     //5、如果为"" 转为null
        String j="";
        String k=Strings.emptyToNull(j);
        System.out.println(k);
        //输出:null

     //6、重复字符串(Strings.repeat)
        String o="123";
        String p=Strings.repeat(o, 3);
        System.out.println(p);
        //输出:123123123

     //7、获取a,b左公共部分字符串(左边第一个公共部分)
        String r="abcdsfsfs";
        String s="accdc3sfsd";
        String t=Strings.commonPrefix(r, s);
        System.out.println(t);
        //输出:a

    //8、获取a,b右公共部分字符串
        String w="faaxyz";
        String x="fwefxyz";
        String z=Strings.commonSuffix(w, x);
        System.out.println(z);
        //输出:xyz
    }
}

guava之Lists、Maps

谷歌提供了guava包里面有很多的工具类,Lists和Maps集合工具,集合操作做了些优化提升。

1、概述

1、静态工厂方法

  (1)Guava提供了能够推断范型的静态工厂方法

List<Person> list = Lists.newArrayList();
Map<KeyType, Person> map = Maps.newLinkedHashMap();

   (2) 用工厂方法模式,我们可以方便地在初始化时就指定起始元素。

Set<Type> copySet = Sets.newHashSet(elements);
List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");

  (3) 通过为工厂方法命名,我们可以提高集合初始化大小的可读性.

List<Type> exactly100 = Lists.newArrayListWithCapacity(100);
List<Type> approx100 = Lists.newArrayListWithExpectedSize(100);
Set<Type> approx100Set = Sets.newHashSetWithExpectedSize(100);

 

二、Lists案例

复制代码
public class ListsTest {

    public static void main(String args[]){

    List<String> list1 = Lists.newArrayList();
        for (int i = 0; i < 10; i++) {
        list1.add(i + "");
    }
        System.out.println("list1: " + list1);
        //输出:list1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

   //2、传入多参数
     List<String> list2 = Lists.newArrayList("1", "2", "3");
        System.out.println("list2: " + list2);
        //输出:list2: [1, 2, 3]

   //3、传入数组
     List<String> list3 = Lists.newArrayList(new String[]{"22", "22"});
        System.out.println("list3: " + list3);
        //输出:list3: [22, 22]

   //4、传入集合
     List<String> list4 = Lists.newArrayList(list1);
        System.out.println("list4: " + list4);
        //输出:list4: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

   //5、使用条件:你确定你的容器会装多少个,不确定就用一般形式的
    //说明:这个容器超过10个还是会自动扩容的。不用担心容量不够用。默认是分配一个容量为10的数组,不够将扩容
    //整个来说的优点有:节约内存,节约时间,节约性能。代码质量提高。
    List<String> list = Lists.newArrayListWithExpectedSize(10);
    //这个方法就是直接返回一个10的数组。
    List<String> list_ = Lists.newArrayListWithCapacity(10);
   }
}
复制代码

 

三、Maps案例

复制代码
public class MapsTest {
        public static void main(String[] args) {

            //1、Maps.newHashMap()获得HashMap();
            Map<Integer, Integer> map0 = Maps.newHashMap();
            for (int i = 0; i < 10; i++) {
                map0.put(i, i);
            }
            System.out.println("map0:" + map0);
            //输出:map0:{0=0, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9}

            //2、传入map0参数构建map
            Map<Integer, Integer> map1 = Maps.newHashMap(map0);
            map1.put(10, 10);
            System.out.println("map1:" + map1);
            //输出:map1:{0=0, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9, 10=10}


            //3、使用条件:你确定你的容器会装多少个,不确定就用一般形式的
            //说明:这个容器超过3个还是会自动扩容的。不用担心容量不够用。默认是分配一个容量为16的数组,不够将扩容
            Map<Integer, Integer> map2 = Maps.newHashMapWithExpectedSize(3);
            map2.put(1, 1);
            map2.put(2, 2);
            map2.put(3, 3);
            System.out.println("map2:" + map2);
            //输出:map2:{1=1, 2=2, 3=3}

            //4、LinkedHashMap<K, V> 有序map
            //Map<Integer,Integer> map3 = Maps.newLinkedHashMap();
            //Map<Integer,Integer> map3 = Maps.newLinkedHashMapWithExpectedSize(11);
            Map<Integer, Integer> map3 = Maps.newLinkedHashMap(map1);
            map3.put(11, 11);
            System.out.println("map3:" + map3);
            //输出:map3:{0=0, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9, 10=10, 11=11}
            
            outMapKeyValue(map3);
            
        }

        /**
         * 遍历Map的四种方法
         */
        private static void outMapKeyValue(Map<Integer, Integer> map3) {

            //1.通过Map.entrySet遍历key和value
            for (Map.Entry<Integer, Integer> integerEntry : map3.entrySet()) {
                System.out.println("key:" + integerEntry.getKey() + " value:" + integerEntry.getValue());
            }

            //2.通过Map.entrySet使用iterator遍历key和value-----不推荐,直接用上面的for each循环代替此方法
            Iterator<Map.Entry<Integer, Integer>> it = map3.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<Integer, Integer> entry = it.next();
                System.out.println("key:" + entry.getKey() + " value:" + entry.getValue());
            }

            //3.通过Map.keySet遍历key;根据key得到value
            for (Integer integer : map3.keySet()) {
                System.out.println("key:" + integer + " value:" + map3.get(integer));
            }

            //4.通过Map.values()遍历所有的value,但不能遍历key
            for (Integer integer : map3.values()) {
                System.out.println("value:" + integer);
            }
        }
}

 

posted @ 2022-02-25 14:23  hanease  阅读(98)  评论(0编辑  收藏  举报