Guava类库知识整理

1.Optional:为什么要用它?因为当有空值得时候 Java的机制是哪里使用了哪里出错,而这个Optional类可以直接指出空值得地方,看出出错地点。
` 常用的方法有: Optional.of(参数) Optional.fromNullable(参数).or(参数) 前后参数类型一致

2.Preconditions: 这个类可以简化很多判断的操作
常用的方法有:Preconditions.checkArgument(boolean f) f=false抛异常
Preconditions.checkArgument(boolean f,String s) 抛出的异常信息 s
Preconditions.checkNotNull(参数) 参数为空抛异常
Preconditions.checkElementIndex(int a,数组的长度) 判断下标是否合法 不合法抛异常
Preconditions.checkPositionIndex(int a,数组的长度) 判断位置上元素是否存在

3.Ordering:这个抽象类实现了Comparetor 它可以更好的用在排序上
常用的方法有: Ordering.natural() 返回一个Ordering<参数是可比较的> 的对象a 这个对象就可以看成是自然排序的比较器
a.sortedCopy(list) 方法返回一个按照自然排序的List集合
Ordering.usingToString() 返回一个Ordering 的对象b 这个对象可以看成是字典顺序排序的比较器
b.sortedCopy(list) 方法返回一个按照字典排序的List集合

        a/b.max/min(list) 返回最大的或者最小的元素

4.ComparisonChain: 这个类 简化了 像Java里的重新equals方法时很多if else 判断
常用的方法有: ComparisonChain.start().compare(a,b).compare(c,d).result() 所有的相等返回0 有不等的返回-1

5.Throwables : 这个类简化了异常和错误的处理
常用的方法有: throw Throwables.propagate(e) 当你解决不了 但是肯定是一个异常时候使用 返回的是运行时异常

        Throwables.propagateIfInstanceOf(t, IOException.class);
            Throwables.propagateIfInstanceOf(t, SQLException.class);
        throw Throwables.propagate(t)  只有异常是 写的那两种才会抛出

        Throwables.propagateIfPossible(t)  Throwable类型为Error或RuntimeException才抛出

6.ImmutableSet : 不可变得Set集合 它实现了set 当需要使用一个set集合 并且不做修改了 使用这个
所有的不可变集合实现都比可变集合更加有效的利用内存 (analysis)
常用的方法有: ImmutableSet.copyOf(set) 复制集合 返回一个ImmutableSet 类型的对象
ImmutableSet.of(“a”, “b”, “c”) 返回一个ImmutableSet 类型的对象
ImmutableSet.builder().add(1).add(2).build(); 返回一个ImmutableSet 类型的对象a

        a.asList() 可以返回成List的集合 这样可以 get(0) 得到值

        ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");//创建一个可以排序的集合
        ImmutableList<String> imList=ImmutableList.of("peida","jerry","harry","lisa","jerry");

7.ImmutableMap : 不可变的Map 线程安全 效率也很高的Key-Value集合
常用的用法有:
ImmutableMap map = ImmutableMap.of(“a”,1,“b”,2) 创建一个集合
map.entrySet() 返回 一个不可变的set集合
map.asMultimap() 返回ImmutableSetMultimap集合
map.get(key)

  1. Multimap : 特点其实就是可以包含有几个重复Key的value,你可以put进入多个不同value但是相同的key,
    但是又不是让后面覆盖前面的内容。
    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>进行去重。
    map.replaceValues(1, Lists.newArrayList(4,5)); 可以替换value的值
    System.out.println(map.toString());
       结果:{1=[4, 5], 2=[3], 4=[2, 3]}

  2. MultiSet : Multiset和Set的区别就是可以保存多个相同的对象。
    在JDK中,List和Set有一个基本的区别,就是List可以包含多个相同对象,且是有顺序的,
    而Set不能有重复,且不保证顺序(有些实现有顺序,例如LinkedHashSet和SortedSet等)
    所以Multiset占据了List和Set之间的一个灰色地带:允许重复,但是不保证顺序。
       常见使用场景:Multiset有一个有用的功能,就是跟踪每种对象的数量,所以你可以用来进行数字统计。
    常见的普通实现方式如下:(单词计数 Java的实现很麻烦 需要map集合 判断值是否null null计数1 否则 +1)
    String strWorld=“wer|dfd|dd|dfd|dda|de|dr”;
    String[] words=strWorld.split("\|");
    List wordList=new ArrayList();
    for (String word : words) {
    wordList.add(word);
    }
    Multiset wordsMultiset = HashMultiset.create();
    wordsMultiset.addAll(wordList);

              for(String key:wordsMultiset.elementSet()){
                 System.out.println(key+" count:"+wordsMultiset.count(key));
                 }
     方法: addAll(集合)  把一个集合可含重复的元素的那种 
         通过 elementSet()得到值key 
         再 count(key)得到个数 这个集合会记录重复的个数
    

    Multiset主要方法:

    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. RangeSet: 这个类是区间的操作 可以减少Java里对多个区间进行if …else 操作
    常用的方法有 :
    RangeSet rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(1, 10));//全是关的
    rangeSet.add(Range.closedOpen(11, 15)); //坐关右闭
    rangeSet.add(Range.closedOpen(15, 20));
    rangeSet.add(Range.openClosed(0, 0));//空的
    rangeSet.remove(Range.open(5, 10));//移除区间
    System.out.println(rangeSet);

               RangeSet<Integer> rangeSet2 = TreeRangeSet.create();
                rangeSet2.add(Range.closed(1, 100));
                boolean r = rangeSet2.contains(6); 
             System.out.println(r); 6是否存在这个区间。
    .encloses(参数为一个区间) 前面的是否包含参数区间 返回Boolean
    
  4. rangeMap : 这个类是把区间带上值了 每个区间对应一个值
    RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
    rangeMap.put(Range.closed(1, 10), “foo”); // {[1, 10] => “foo”}
    rangeMap.put(Range.open(3, 6), “bar”); // {[1, 3] => “foo”, (3, 6) => “bar”, [6, 10] => “foo”}
    rangeMap.put(Range.open(10, 20), “foo”); // {[1, 3] => “foo”, (3, 6) => “bar”, [6, 10] => “foo”, (10, 20) => “foo”}
    rangeMap.remove(Range.closed(5, 11)); // {[1, 3] => “foo”, (3, 5) => “bar”, (11, 20) => “foo”}

     rangeMap.get(int a) 得到值
    
  5. maps : 操作两个map更容易,有好几个方法都是对map操作的
    常用的方法有:
    Map<String, Integer> left = ImmutableMap.of(“a”, 1, “b”, 2, “c”, 3);
    Map<String, Integer> right = ImmutableMap.of(“c”,3,“a”, 1, “b”, 2);
    MapDifference<String, Integer> diff = Maps.difference(left, right);
    System.out.println(diff);//找出两个map不同的地方

        //entriesInCommon() 两个 Map 中都有的映射项,包括匹配的键与值
                //entriesDiffering() 键相同但是值不同值映射项。返回的 Map 的值类型为MapDifference.Valu
                //eDifference,以表示左右两个不同的值
               //entriesOnlyOnLeft() 键只存在于左边 Map 的映射项
            //entriesOnlyOnRight() 键只存在于右边 Map 的映射项
            Map<String,Integer> commen = diff.entriesInCommon();
            System.out.println(commen);//在不同的diff基础上 还能得到相同的之类的
    
  6. BiMap: BiMap提供了一种新的集合类型,它提供了key和value的双向关联的数据结构。
    Java中map都是通过key找value 而这个集合是双向的。实现类HashBiMap
    public void BimapTest(){
    BiMap<Integer,String> logfileMap = HashBiMap.create();
    logfileMap.put(1,“a.log”);
    logfileMap.put(2,“b.log”);
    logfileMap.put(3,“c.log”);
    System.out.println(“logfileMap:”+logfileMap);
    BiMap<String,Integer> filelogMap = logfileMap.inverse();
    System.out.println(“filelogMap:”+filelogMap);
    }
    完美解决了key-value互换的操作 但是值得注意的是 inverse()这个方法其实就是种在视图的基础上反转的
    所以logfileMap和filelogMap 其实还是同一个map 修改哪个另一个都会改变,而且这个BiMap对于value要有很高 也必须要唯一
    否则报错

  7. Table : 当我们需要多个索引的数据结构的时候,通常情况下,我们只能用这种丑陋的Map<FirstName, Map<LastName, Person>>
    来实现。为此Guava提供了一个新的集合类型-Table集合类型,来支持这种数据结构的使用场景。
    Table支持“row”和“column”,而且提供多种视图。 实现类 HashBasedTable

    创建方式: Table<String, Integer, String> aTable = HashBasedTable.create(); 有三个参数
    Table<Integer, Integer, String> aTable = HashBasedTable.create();
    aTable.put(1,1,“1-1”);
    aTable.put(1,2,“1-2”);
    aTable.put(2,1,“1-1”);
    aTable.put(2,2,“1-2”);
    System.out.println(aTable);
    System.out.println(aTable.get(2,2));
    System.out.println(aTable.column(1));
    想获取啥获取啥 可以看成是一个表了 三维的。有多少值 size() 就多大

  8. Cache : cache 就是为了提升系统性能而开辟的一块内存空间。
    通常来说,Guava Cache 适用于:
    -你愿意消耗一些内存空间来提升速度。
    -你预料到某些键会被查询一次以上。
    -缓存中存放的数据总量不会超出内存容量

    Guava Cache有两种创建方式:(接口是 LoadingCache)

    1. cacheLoader
    

2. callable callback

    通过这两种方法创建的cache,和通常用map来缓存的做法比,不同在于,
    这两种方法都实现了一种逻辑——从缓存中取key X的值,如果该值已经缓存过了,则返回缓存中的值,
    如果没有缓存过,可以通过某个方法来获取这个值。但不同的在于cacheloader的定义比较宽泛,
    是针对整个cache定义的,可以认为是统一的根据key值load value的方法。
    而callable的方式较为灵活,允许你在get的时候指定。

cacheLoader的创建:

public void TestLoadingCache() throws Exception{

    LoadingCache<String,String> cacheBuilder = CacheBuilder.newBuilder().build(new CacheLoader<String, String>() {
        
        public String load(String key) throws Exception {
            return "hello"+key+"!";
        }
    });

    cacheBuilder.put("jj","aa");
    System.out.println(cacheBuilder.get("jj"));
    System.out.println(cacheBuilder.get("jj22"));
    }
当没有put(key,value) 取出来的就是默认定义好的返回值
callable的创建:

public void callableTest() throws ExecutionException {
    Cache<String, String> callable = CacheBuilder.newBuilder().build();
    String str = callable.get("jj", new Callable<String>() {
        public String call() throws Exception {
            return "hello"+"jj";
        }
    });
    System.out.println(str);

    }



缓存里常用的方法:1.单独移除用 Cache.invalidate(key)

2.批量移除用 Cache.invalidateAll(keys)
   3.移除所有用 Cache.invalidateAll()
4.大小的设置 CacheBuilder.maximumSize(long)
CacheBuilder.weigher(Weigher) CacheBuilder.maxumumWeigher(long)
5.三种基于时间的清理或刷新缓存数据的方式:
expireAfterAccess: 当缓存项在指定的时间段内没有被读或写就会被回收。
expireAfterWrite:当缓存项在指定的时间段内没有更新就会被回收。
refreshAfterWrite:当缓存项上一次更新操作之后的多久会被刷新。

**    我的理解就是当你的操作结果很重要,你就可以使用缓存,当你有固定的关联格式就使用CacheLoader,
    不固定需要覆盖就使用Callable的方式,就把它看成是一种特殊的Map 还能设置回收一下
  1. 字符串(常用的方法或是类) :
    连接器 joiner:
    joiner.on(“连接符”).skipNulls()去null
    joiner.join(“first”,“second”…) 把迭代的连接起来

    Strings :
          判断字符串是否为null 或 空: Strings.isNullOrEmpty(str)
         Strings.commonPrefix(a,b) 获取两个串相同的前缀
         Strings.commonSuffix(c,d) 获取两个串相同的后缀
         String padEndResult = Strings.padEnd("你好", 4, '0'); 补全字符串 4 是最小的长度 不够就在后面补 0
         String padStartResult = Strings.padStart("2", 2, '0'); 在前面补 0
    
    Splitter:拆分字符串
                Iterable<String> splitResults = Splitter.onPattern(",|,").trimResults()
                                    .omitEmptyStrings().split("hello,word,,世界,水平");
    
                    for (String item : splitResults) {
                        System.out.println(item);
                    }
        我感觉这个方法跟Java的拆分也差不多
        Splitter的onPattern方法传入的是一个正则表达式,其后紧跟的trimResults()方法
        表示要对结果做trim,omitEmptyStrings()表示忽略空字符串,split方法会执行拆分操作。
        split返回的结果为Iterable<String>,我们可以使用for循环语句来逐个打印拆分字符串的结果。
        
        ** 它最牛的是二次拆分 例如我们可以将a=b;c=d这样的字符串拆分成一个Map<String,String>。
        String toSplitString = "a=b;c=d,e=f";
               Map<String,String> kvs = Splitter.onPattern(",|;").withKeyValueSeparator('=').split(toSplitString);
        这个kvns:{a=b, c=d, e=f}  这个比Java的好用
    
    拆分成map 也有把map合并成字符串 :
         Map<String,String> map = new HashMap<String,String>();
                map.put("a", "b");
                map.put("c","d");
                String mapJoinResult = Joiner.on(",").withKeyValueSeparator("=").join(map);
             System.out.println(mapJoinResult);
    
    记住这个方法 Joiner.withKeyValueSeparator("=") key和value的标识符 在连接里就是连接用 拆分里就是拆分用
    

16.CharMatcher : 跟正则很像,不过操作字符串的方法更多
CharMatcher.isNot(‘a’).removeFrom(“abacd”) 把不是a 的全都移除 或者改成 is
CharMatcher.WHITESPACE.replaceFrom(“a bcd”,‘f’) 把空格替换成 f
CharMatcher.DIGIT.replaceFrom(“a4bcd”,“f”) 把数字替换 f
CharMatcher.anyOf(“ab”).trimFrom(“abacatabb”) ab中任何一个 去掉字符串前面跟后面的ab直到不是a不是b为止

    以上方法返回的都是String 下面返回Boolean
    boolean matchesAllOfResult = CharMatcher.JAVA_UPPER_CASE.matchesAllOf("hcd");  检查字符串是否全匹配
                     CharMatcher.JAVA_UPPER_CASE.matchesAnyOf("hcd")  匹配上一个就行

16.CaseFormat :CaseFormat用来转换各种不同的编程语言间的变量名命名格式,
主要用到的方法只有一个 CaseFormat.to(CaseFormat from, String s)
CaseFormat fromFormat = CaseFormat.LOWER_CAMEL;
CaseFormat toFormat = CaseFormat.UPPER_CAMEL;
String s = “lowerCamel”;
System.out.println(fromFormat.to(toFormat, s));
用处还没发现
17.EventBus : EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。
对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。

  ** 观察者模式(Observer):观察者模式中,需要一个 事件的发布者--主题事件订阅者--收取消息的用户,
                     Guava中Event---就是消息发送和接收者之间的一个信物。

    在以下情况下可以使用 Observer 模式:
    当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中
                  以使它们可以各自独立地改变和复用。
    当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
    当一个对象必须通知其他对象,而它又不能假定其他对象是谁。

最简单的例子 :  
         发布消息的类:
         public class TestEvent {
            //生产者-消息封装类
            private final int message;
            public TestEvent(int message) {
                this.message = message;
             System.out.println("event message:"+message);
            }
            public int getMessage() {
                return message;
                }
         }

        接收消息的类:
            public class EventListener {

                    //消息接受类
               public int lastMessage = 0;

                @Subscribe
               public void listen(TestEvent event) {
                lastMessage = event.getMessage();
                   System.out.println("Message:"+lastMessage);
                    }

               @Subscribe
                    public void listen2(DeadEvent event) {
                    //死亡事件进这里 (传递的参数不是正常想要的监听)
                System.out.printf("%s=%s from dead events%n", event.getSource().getClass(), event.getEvent());
                    }

                public int getLastMessage() {
                    return lastMessage;
                    }
            }
        测试的类(最重要的类 因为用了EventBus):

            public class TestEventBus {

                //测试类
                public static void main(String[] args) throws Exception {

                EventBus eventBus = new EventBus();
                EventListener listener = new EventListener();

                eventBus.register(listener);//register方法来订阅事件 把接收类放进去
            //只需要在订阅方法上标注上@Subscribe和 *保证只有一个输入参数的方法就可以搞定
                eventBus.post(new TestEvent(200));//通过post方法发布事件
                eventBus.post(new TestEvent(300));
                eventBus.post(new TestEvent(400));
                eventBus.post("2");//这个因为不满足正常的监听 类型不对 算是 死亡的事件

                System.out.println("LastMessage:"+listener.getLastMessage());
                    }
            }
    

        总结一下: 最主要的是  @Subscribe 方法上带这个 就是订阅者订阅的方法
               运用 EventBus.register(订阅者)  EventBus.post(发布消息者)

    它还有一个特点 假如 Integer Number 两个类都是接收消息的  你在post()里发布了一个Integer类型的 两者都能接收
    但是 你传了Long型的 只有Number能接收到  所以 子类能接收的 它的父类肯定能接收

    eventBus.unregister(this); 可以取消监听 不影响其他的在监听

18.ListenableFuture : 多线程 在代码中多使用 ListenableFuture 来代替 JDK 的 Future, 因为:
大多数 Futures 方法中需要它。
转到 ListenableFuture 编程比较容易。
Guava 提供的通用公共类封装了公共的操作方方法,不需要提供 Future 和 ListenableFuture 的扩展方法。

    这个类使用观察者模式为在异步计算完成之后马上执行addListener指定一个Runnable对象,从实现“完成立即通知”。


    ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
    ListenableFuture<String> futureTask = executorService.submit(new Callable<String>() { //创建ListenaleFuture对象
                @Override
                public String call() throws Exception {
                    return "Task completed";
                }
            });
    FutureCallbackImpl callback = new FutureCallbackImpl();
    Futures.addCallback(futureTask, callback); //添加回调
    callback.getCallbackResult(); //获取结果
    如果CallBack是一个耗时操作,你应该选择另一个注册CallBack:
    Futures.addCallback(futureTask,callback,executorService); //提供另一个线程池来执行性回调

--------------------------------------------------------------------------------------------------------------我是分割线

Java Future 的意义:
在并发编程时,一般使用runnable,然后扔给线程池完事,这种情况下不需要线程的结果。所以run的返回值是void类型。

如果是一个多线程协作程序,比如菲波拉切数列,1,1,2,3,5,8...使用多线程来计算。但后者需要前者的结果,就需要用callable接口了。 
callable用法和runnable一样,只不过调用的是call方法,该方法有一个泛型返回值类型,你可以任意指定。 
(实现runnable 是无返回值  实现callable 有返回值 根据范型决定)

线程是属于异步计算模型,所以你不可能直接从别的线程中得到函数返回值。 
这时候,Future就出场了。Futrue可以监视目标线程调用call的情况,当你调用Future的get()方法以获得结果时,
当前线程就开始阻塞,直接call方法结束返回结果。

java线程池:
1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。

Executors创建线程池的几种常见方式:

    通过Executors可以创建不同类似的线程池,常见的大概有下表几种类型,还有些可能未被列出。
在实际应用中,个人感觉主要使用newCachedThreadPool和newFixedThreadPool来创建线程池。

newCachedThreadPool类: 缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse;
        如果没有,就建一个新的线程加入池中。缓存型池子通常用于执行一些生存期很短的异步型任务。

newFixedThreadPool类: 和cacheThreadPool类似,有可用的线程就使用,但不能随时建新的线程。
        其独特之处:任意时间点,最多只能有固定数目的活动线程存在,
        此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止
        直接被移出池子。cache池和fixed池调用的是同一个底层池,
        只不过参数不同:fixed池线程数固定,并且是0秒IDLE(无IDLE)。
        所以FixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器。

ScheduledThreadPool类: 调度型线程池。这个池子里的线程可以按schedule依次delay执行,或周期执行。

SingleThreadExecutor类: 单例线程,任意时间池中只能有一个线程。用的是和cache池和fixed池相同的底层池。

1、MoreExecutors

       该类是final类型的工具类,提供了很多静态方法。例如listeningDecorator方法初始化ListeningExecutorService方法,
   使用此实例submit方法即可初始化ListenableFuture对象。

2、ListeningExecutorService

       该类是对ExecutorService的扩展,重写ExecutorService类中的submit方法,返回ListenableFuture对象。

3、ListenableFuture

       该接口扩展了Future接口,增加了addListener方法,该方法在给定的excutor上注册一个监听器,当计算完成时会马上调用该监听器。
   不能够确保监听器执行的顺序,但可以在计算完成时确保马上被调用。

4、FutureCallback

       该接口提供了OnSuccess和OnFailuren方法。获取异步计算的结果并回调。

5、Futures

       该类提供和很多实用的静态方法以供使用。

6、ListenableFutureTask

       该类扩展了FutureTask类并实现ListenableFuture接口,增加了addListener方法。

----------------------------------------------------------------------------------------------------------------------我是分割线

下面这段代码解释了为什么要用guava的ListenableFuture好处:

public class FutureTest {

    public static class Task implements Callable<String> {
        @Override
        public String call() throws Exception {
            String tid = String.valueOf(Thread.currentThread().getId());
            System.out.printf("Thread#%s : in call\n", tid);
            return tid;
            }
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        List<Future<String>> results = new ArrayList<Future<String>>();
        ExecutorService es = Executors.newCachedThreadPool();
        for(int i=0; i<100;i++)
            results.add(es.submit(new Task()));

        for(Future<String> res : results)
            System.out.println(res.get());
        }

}
    实现Callable 会产生返回值 用list集合 接收 接收到的返回值 在for循环里 调用get()方法获取值
    但是你用了Guava的 自己就监控完成没有 完成了直接自己调用。
    ExecutorService pool = Executors.newFixedThreadPool(2);

    pool.submit(new CallableDemo());

    pool.submit(new CallableDemo());
        这样就是开启了两个线程

------------------------------------------------------------------------------------------------------------------我是分割线

使用 guava 的写法:
public class MyTest {

    static int count = 100;

    public static void main(String[] args) {

        ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(3));
        ListenableFuture<List<String>> listenableFuture = executorService.submit(new Callable<List<String>>() {

            public List<String> call() throws Exception {
                List<String> list = newArrayList();
                while (count>=0) {
                    list.add(count);
                    count--;
                }
                return list;
            }
        });

        Futures.addCallback(listenableFuture, new FutureCallback<List<String>>() {
            public void onSuccess(List<String> result) {
               for(String s:result){
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println(s);
                   }
            }

            public void onFailure(Throwable t) {
                System.out.println("失败");
                    }
            });
        }
}

    并发结束。

---------------------------------------------------------------------------------------------------------------------------------我是分割线

   Files 类的简单实用:

    //复制移动文件  
    File from=new File("D:\\you.txt");  
    File to=new File("D:\\wo.txt");  
    Files.copy(from, to);  
    //Files.move(from, to);//会删除掉原来的文件  
      
    //一行代码读取内容存入list中  
    List<String> list=Files.readLines(from, Charsets.UTF_8);  
      
    //一行代码对文件进行内容的追加 1  
    Files.append("zhuijianeirong",to,Charsets.UTF_8);  



 // 下载文件

Closer closer = Closer.create();
InputStream in = closer.register(new URL(“http://ssss_.mp3”).openStream());
File to = new File(“D:/aaa.mp3”);
Files.write(ByteStreams.toByteArray(in), to);
System.out.println(to.getAbsolutePath());

  1. Function:函数式编程

    函数的最大用途是对集合元素进行各种转换

    List lower = Lists.newArrayList(“aa”,“bb”);

    List upper = Lists.transform(lower,new Function<String,String>(){

                   public String toup(String s){
    
                              return s.toUpperCase();
    
                   }
    
    });
    

21.Predicate:谓词(断言)

最常用的功能是,使用Predicate对集合进行过滤。

Set lower = Sets.newHashSet(“aa”, “bb”);
Set notbb = Sets.newHashSet();
notbb = Sets.filter(lower, new Predicate() {

public boolean apply(String s) {
    return !"bb".equals(s);
}

});
for (String s : notbb) {
System.out.println(s);
}
List intList = Lists.newArrayList(1, 2, 3, 5, 6);

Predicate predicate = new Predicate() {

public boolean apply(Integer value) {

return value != 3 && value != 5; } };

List resultList = Lists.newArrayList(Iterables.filter(intList, predicate));

System.out.println(resultList);

Guava类库中的Table是一个双键的Map,可以理解为一个行列式的数据结构。 Table可以用来表示一个映射,其中每个键都有一个与之关联的值,而且这个键需要由两个参数来确定。在Table中,第一个键称为"行键",第二个键称为"列键",而对应的值称为"值"。 Table的实现方式可以看作是一个Map<RowKey, Map<ColumnKey, Value>>的嵌套结构,其中RowKey和ColumnKey分别表示行键和列键,Value表示对应的值。 Table提供了多种视图,包括行视图、列视图、单元格视图等,这些视图可以方便地进行表格的操作和查询。 下面是一个简单的示例代码: ```java Table<String, String, Integer> table = HashBasedTable.create(); table.put("row1", "col1", 1); table.put("row1", "col2", 2); table.put("row2", "col1", 3); table.put("row2", "col2", 4); System.out.println(table.get("row1", "col1")); // 输出1 System.out.println(table.row("row1")); // 输出{col1=1, col2=2} System.out.println(table.column("col1")); // 输出{row1=1, row2=3} System.out.println(table.cellSet()); // 输出[(row1,col1)=1, (row1,col2)=2, (row2,col1)=3, (row2,col2)=4] ``` 在上面的示例中,我们创建了一个Table对象,并往其中添加了四个元素。然后,我们分别通过get方法、row方法、column方法和cellSet方法获取了对应的视图,并输出了它们的内容。 需要注意的是,Table中的行键、列键和值都可以为null,但是在使用时需要特别注意空指针异常的问题。此外,Table中的行键和列键必须实现equals和hashCode方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值