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); } } }