楼主: Sky-Tiger

Google? Evil? You have no idea

[复制链接]
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
11#
 楼主| 发表于 2014-4-19 23:04 | 只看该作者
Batteries loaded resolution
sbt comes out of the box with a few configured repositories:
Maven Central
Typesafe releases
sbt community releases
These repositories contain a significant portion of JVM-related dependencies, and are starting to see the addition of Javascript dependencies. Most likely, for simple projects, configuring new resolvers is unnecessary.
Now that we have a location from where we’ll pull artifacts, let’s start configuring what artifacts to pull. If you recall from chapter’s 1 and 2, we had these dependencies configured:
libraryDependencies ++= Seq("junit" % "junit" % "4.11" % "test", "org.specs2" % "specs2_2.9.1" % "1.10" % "test")
Here we’re adding to the libraryDependencies setting two dependencies for JUnit and Specs2. The libraryDependencies settings is defined as a collection of ModuleID values. ModuleID is an sbt abstraction to simplify the declaration of dependencies.
ModuleID consists of three mandatory values organization, name and revision. These are ivy’s variant of Maven's groupId, artifactId and version attributes, and are a way to uniquely identify a library. Usually we won’t be directly creating ModuleIDs, and instead will use sbt’s shortcuts, as we do above.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
12#
 楼主| 发表于 2014-4-29 20:58 | 只看该作者
Imagine a C
or C++ developer who already has the burden of managing their own memory
usage in their single-threaded application.  In a multi-core world, they now have to
do so across multiple threads at the same time, while also trying to figure out who
has the ability to access shared mutable memory at what time.  This makes
something that was already very hard to do and verify in the first place into
something that is daunting for even the most senior C/C++ developers.
This has led to a veritable “Renaissance” in functional programming; more
languages have designed constructs that follow the functional approach because the
paradigm is more supportive of reasoning about problems in concurrent and
parallelized applications.  By writing code in a functional style, developers have an
easier time reasoning about what their application is doing at any given point in
time.
The core concepts of functional programming have been around for many
years, defined through Lambda Calculus by Alonzo Church  in the 1930s.
7
However, the essence of functional programming is the idea that programs can be
written using pure mathematical functions (and therefore maintaining  of our purity
functions) - those that return the same value every time when passed the same
inputs - that do not incur any “side effects” (see section below).  This relationship
to mathematics is important - the core ideas of functional programming are that the
way you write code is analogous to how functions are composed in math.   With all
of these powerful tools at our disposal, it is truly a wonderful time to be a
programmer again because we can solve our problems with languages that support
one or both paradigms simultaneously.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
13#
 楼主| 发表于 2014-4-29 20:59 | 只看该作者
The  java.util.function.Predicate<T> interface defines an abstract method named  test,
which accepts an object of generic type T and returns a boolean. It is exactly the same one
that you created yourself earlier but is available out of the box! You might want to use this
interface when you need to represent a boolean expression that uses an object of type T. For
example, you can define a lambda that accepts String objects:
public interface Predicate<T>{
    public boolean test(T t);
}
public static <T> List<T> filter(List<T> list, Predicate<T> p) {
    List<T> results = new ArrayList<>();
for(T s: list){
        if(p.test(s)){
            results.add(s);
        }
    }
return results;
}
Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
List<String> nonEmpt = filter(listOfStrings, nonEmptyStringPredicate);
If you look up the Javadoc specification of the Predicate interface you may notice additional
methods such as  and and  or. Don’t worry about them for now.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
14#
 楼主| 发表于 2014-4-29 20:59 | 只看该作者
The java.util.function.Consumer<T> interface defines an abstract method named accept,
which takes an object of generic type  T and returns no result (void).  You might use this
interface when you need to access an object of type T and perform some operations on it. For
example, you can use it to create a method forEach, which takes a list of Integer and applies
an operation on each element of that list in order. In the  following  example we use this
forEach method combined with a lambda to print all the elements of the list:
public interface Consumer<T>{
    public void accept(T t);
}
public static <T> void forEach(List<T> list, Consumer<T> c){
    for(T i: list){
        c.accept(i);
    }
}
forEach(
         Arrays.asList(1,2,3,4,5),
        (Integer i) -> System.out.println(i) #A
       );
#A: The lambda is the implementation of the accept method from Consumer

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
15#
 楼主| 发表于 2014-4-29 20:59 | 只看该作者
The  java.util.function.Function<T, R> interface defines an abstract method named
apply, which takes an object of generic type T as input and returns an object of generic type
R. You might use this interface when you need to define a lambda that can extract information
from the input object (for example, extracting the weight of an apple) or transform the input
(for example, a string to its length). In the code that follows we show how you can use it to
create a method map to transform a list of String into a list of Integer containing the length
of each String:
public interface Function<T, R>{
    public R apply(T t);
}
public static <T, R> List<R> map(List<T> list,
                                Function<T, R> f) {
    List<R> result = new ArrayList<>();
for(T s: list){
        result.add(f.apply(s));
    }
return result;
}
// [7, 2, 6]
List<String> l = map(
                       Arrays.asList("lambdas","in","action"),
                       (String s) -> s.length() #A
               );
#A: The lambda is the implementation for the apply method of Function
PRIMITIVE SPECIALIZATIONS
We described three functional interfaces that are generic: Predicate<T>, Consumer<T>, and
Function<T, R>. There are also functional interfaces that are specialized with certain types.
To refresh a little: every Java type is either a reference type (for example, Byte, Integer,
Object,  List) or a primitive type (for example, int,  double,  byte,  char).  But generic
parameters (for example the T in Consumer<T>) can only be bound to reference types. This is
due to how generics are internally implemented. Some other languages such as C# don’t have
this restriction. Other languages such as Scala only have reference types. As a result, in Java
there’s a mechanism  to convert a primitive type into a corresponding reference type. This
mechanism is called  boxing. The dual (that is, converting a reference type into a
corresponding primitive type) is called unboxing. Java has also a mechanism called autoboxing
to facilitate the task for programmers: boxing and unboxing operations are done
automatically.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
16#
 楼主| 发表于 2014-4-29 21:54 | 只看该作者
In a purely functional program, mutable state is impure and considered
dangerous—the same name for a variable can refer to something different at
different points in time.  Mutable state is any variable that is not stable or final, and
can be changed or updated inside of an application.  By using final, immutable
values in an application, a programmer has a greater ability to reason about what a
value will be at a given time, because they know that no one else can possibly have
changed it.  This is the basis for immutable data structures, where any action
performed on the data structure results in a new data structure being created that
represents the updated view.  The original data structure, however, has remained
unchanged, and any other part of the program that continues to use it does not see
the change that was made.
By leveraging immutability throughout an application, a developer is able to
limit the places where mutation can take place to a very small section of code.  In
doing so, the possibility of contention, where multiple threads are attempting to
access the same resource at the same time and some are forced to wait their turn, is
limited in scope to a small region.  Contention is one of the biggest prices to pay
when trying to make an application by using multiple CPU cores, and should be
avoided as much as possible.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
17#
 楼主| 发表于 2014-5-3 23:24 | 只看该作者
Here you use a three-argument overloaded version of the reducing method investigated in section 5.1.1, which considered the one-argument form:
• The first argument is the starting value of the reduction operation and will also be the value returned in case of a Stream with no elements, so clearly 0 is the appropriate value in case of a numeric sum.
• The second argument is the same function we used in section 5.1.2 to transform a Dish into an int representing its calorie content.
• The third argument is a BinaryOperator, which aggregates two items into a single value of the same type. In the previous code this just sums two ints.
You can think of the Collector created with the one-argument reducing factory method as a particular case of this one, generated by the three-argument method, which uses the first item in the Stream as a starting point and an identity function (that is, a function doing nothing more than returning its input argument as it is) as a transformation function. This also implies that the one-argument reducing Collector won’t have any starting point when passed to the collect method of an empty Stream and, as you’ve seen before, this is the reason it returns an Optional.EMPTY. Because this three-argument version of the reducing method already provides a more meaningful value when given an empty Stream (as you saw in figure 5.1), it can directly return the actual result of the collection operation instead of an Optional

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
18#
 楼主| 发表于 2014-5-3 23:25 | 只看该作者
Here you use a three-argument overloaded version of the reducing method investigated in section 5.1.1, which considered the one-argument form:
The first argument is the starting value of the reduction operation and will also be the value returned in case of a Stream with no elements, so clearly 0 is the appropriate value in case of a numeric sum.
The second argument is the same function we used in section 5.1.2 to transform a Dish into an int representing its calorie content.
The third argument is a BinaryOperator, which aggregates two items into a single value of the same type. In the previous code this just sums two ints.
You can think of the Collector created with the one-argument reducing factory method as a particular case of this one, generated by the three-argument method, which uses the first item in the Stream as a starting point and an identity function (that is, a function doing nothing more than returning its input argument as it is) as a transformation function. This also implies that the one-argument reducing Collector won’t have any starting point when passed to the collect method of an empty Stream and, as you’ve seen before, this is the reason it returns an Optional.EMPTY. Because this three-argument version of the reducing method already provides a more meaningful value when given an empty Stream (as you saw in figure 5.1), it can directly return the actual result of the collection operation instead of an Optional

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
19#
 楼主| 发表于 2014-5-3 23:27 | 只看该作者
We already observed in chapter 4 that there’s another way to perform the same operation without using a Collector—by mapping the Stream of Dishes into one of Integers, transforming each Dish into the number of calories it contains, and then reducing this last Stream with the same method reference used in the last statement:
int totalCalories = menu.stream().map(Dish::getCalories).reduce(Integer::sum).get();
Note that, like the result of the Collectors generated by one-argument reducing, the reduce method of the Stream class doesn’t return an int but an Optional<Integer> to manage in a null-safe way the case of a reduction operation over an empty Stream. Finally, and even more concisely, you can achieve the same result by mapping the Stream to an IntStream and then invoking the sum() method on it:
int totalCalories = menu.stream().mapToInt(Dish::getCalories).sum();

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
20#
 楼主| 发表于 2014-5-3 23:36 | 只看该作者
Once again, this demonstrates how functional programming in general, and the new API based on its principles added to the Collection Framework in Java 8 in particular, very often provides multiple ways to perform the same operation. This example also shows that Collectors are somewhat more complex to use than the methods directly available on the Stream interface, but in exchange, they offer higher levels of abstraction and generalization and are more reusable and customizable.
Our suggestion is to explore the largest number of possible solutions for the problem at hand, but always choose the most specialized one that’s general enough to solve it. This is often the best decision for both readability and performance reasons. For instance, to calculate the total calories in our menu we’d prefer the last solution (using IntStream) because it’s the most concise and very likely also the most readable one. At the same time, it’s also the one that performs best, because the IntStream allows us to avoid all the auto-unboxing operations, or implicit conversions from Integer to int, that are useless in this case.

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表