搜索词>>java ee 8 耗时0.0030
  • Java EE 8 JSON Pointer讲解

    Java EE 8 JSON Pointer讲解,Java EE 8包含JSON处理API的更新,并为最新的JSON标准提供最新的IEFT标准。Java EE 8包含JSON处理API的更新,并为最新的JSON标准提供最新的IEFT标准。他们是: <ul> <li>JSON Pointer (RFC 6901)</li> <li>JSON Patch (RFC 6902)</li> <li>JSON Merge Patch (RFC 7396)</li> </ul>   <h2 style="margin-left:0px; margin-right:0px; text-align:start">入门</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff">要开始使用JSON-P,您需要Maven中央存储库中的以下依赖项。</span></span></span></p> <pre> <code class="language-xml"><dependency> <groupId>javax.json</groupId> <artifactId>javax.json-api</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>javax.json</artifactId> <version>1.1</version> </dependency></code></pre> <h2>JSON-Pointer</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff">JSON指针定义了一个字符串表达式,该表达式引用JSON文档的层次结构内的元素。通过JSON指针表达式,您可以通过检索,添加,删除和替换由表达式引用的元素或值来访问和操作JSON文档。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff">入口API是<em><strong>javax.json.JsonPointer</strong></em>接口。通过调用<em><strong>javax.json.Json</strong></em>  类上的静态工厂方法<strong><em>createPointer(String expression)</em></strong>并将其传递给指针表达式来创建实例。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start">检索一个值</h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff">如果下面给出了JSON文档,并且您想要检索<strong><em>title</em></strong>元素的值,则可以创建JSON指针表达式  <em><strong>/title</strong></em>。</span></span></span></p> <pre> <code class="language-json">{ "title": "Java EE: Only What's New", "author": "Alex Theedom", "chapters": [ "Chapter 1: Java EE 8 What’s New Overview", "Chapter 2: Java API for JSON Binding 1.0 (JSR 367)", "Chapter 3: Java EE Security API 1.0 (JSR 375)" ], "released": true, "pages": 300, "sourceCode": { "repositoryName": "Java-EE-8-Only-Whats-New", "url": "github.com/readlearncode/" }, "otherBooks": [ { "title": "Professional Java EE Design Patterns", "length": 350 } ] } </code></pre> <pre> <code class="language-java">JsonObject jsonObject = ... create JSONObject from JSON document ...;</code></pre> 下面的代码片段创建一个<strong><em>JsonPointer</em> </strong>并引用<em><strong>title</strong> </em>元素。然后它调用传递<em><strong>JsonObject</strong></em>来查询的<strong><em>getValue()</em></strong>方法。 <pre> <code class="language-java">JsonValue jsonValue = Json.createPointer(“/ title”)。getValue(jsonObject);</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start">添加一个值</h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff">要向JSON文档添加(或插入)值,请遵循与检索相同的逻辑,方法是使用JSON指针表达式来标识文档中的插入点。以下代码片段将新的<em><strong>“category”:“</strong></em></span></span></span><em><strong>Programming</strong></em><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff"><em><strong>”</strong></em> JSON对象添加到文档的根目录。</span></span></span></p> <pre> <code class="language-java">JsonObject jsonObject = Json .createPointer("/category") .add(jsonObject, Json.createValue("Programming"));</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff">返回的<em><strong>JsonObject</strong> </em>是整个新的修改对象。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start">删除一个值</h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff">删除过程需要将删除的值的位置表示为JSON指针表达式。下面的代码片段删除<em><strong>title</strong> </em>元素,并将修改的JSON文档作为<em><strong>JsonStructure</strong> </em>实例返回</span></span></span></p> <pre> <code class="language-java">JsonStructure jsonStructure = Json.createPointer(“/ title”)。remove(jsonObject);</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start">替换一个值</h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff">要替换要替换的元素的JSON指针表达式,并将替换元素传递给<em><strong>replace()</strong></em>方法。下面的代码片段替换<strong><em>title</em> </strong>元素的值并返回修改后的JSON文档。</span></span></span></p> <pre> <code class="language-java">JsonStructure jsonStructure = Json .createPointer("/title") .replace(jsonObject, Json.createValue("Java EE 8"));</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start">测试一个值</h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff">可以使用<em><strong>containsValue()</strong> </em>方法测试某个位置存在的值。下面的代码片段测试以查看它在由JSON指针表达式<em><strong>/ doesNotExist</strong></em>表示的位置处有一个值。</span></span></span></p> <pre> <code class="language-java">Boolean containsValue = Json .createPointer("/doesNotExist") .containsValue(jsonObject);</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">总结结</h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:"Noto Sans",sans-serif"><span style="color:#000000"><span style="background-color:#ffffff"><span style="font-family:inherit">上面这些,这就是关于JSON Processing新功能的第一篇文章。</span></span></span></span></p>
  • Java EE 8最受关注的新特性或者说最重要的新特性

    备受期待的Java Enterprise Edition 8发布了两个令人兴奋的新API(JSON-Binding 1.0和Java EE Security 1.0)并改进了当前的API(JAX-RS 2.1,Bean Validation 2.0,JSF 2.3,CDI 2.0,JSON-P 1.1,JPA 2.2和Servlet 4.0)。这是Oracle企业Java平台近四年来的第一个版本,它包含数百个新功能,更新的功能和错误修复。那么最好的新功能是什么?<h2>前言</h2> <blockquote> <p>    备受期待的Java Enterprise Edition 8发布了两个令人兴奋的新API(JSON-Binding 1.0和Java EE Security 1.0)并改进了当前的API(JAX-RS 2.1,Bean Validation 2.0,JSF 2.3,CDI 2.0,JSON-P 1.1,JPA 2.2和Servlet 4.0)。这是Oracle企业Java平台近四年来的第一个版本,它包含数百个新功能,更新的功能和错误修复。那么最好的新功能是什么?</p> </blockquote> <h2 style="margin-left:0px; margin-right:0px; text-align:start">前5个新功能</h2> <ul> <li><strong>新的安全API:注释驱动的身份验证机制</strong></li> </ul> 全新的安全API包含三项出色的新功能:身份库抽象,新的安全上下文以及新的注释驱动的身份验证机制,这些机制会使web.xml文件声明过时。最后一个是我今天要讨论的内容。 <ul> <li><strong>JAX-RS 2.1:新的被动式客户</strong></li> </ul> 端JAX-RS 2.1中的新型被动式客户端,采用反应式编程风格并允许组合端点结果。 <ul> <li><strong>新的JSON绑定API</strong></li> </ul> 新的JSON绑定API,为JSON序列化和反序列化提供本机Java EE解决方案。 <ul> <li><strong>CDI 2.0:在Java SE中使用CDI 2.0中</strong></li> </ul> 有趣的新功能允许在Java SE应用程序中引导CDI。 <ul> <li><strong>Servlet 4.0:服务器推送Servlet 4.0中</strong></li> </ul> 的服务器推送功能将servlet规范与HTTP / 2对齐。<br />   <h2 style="margin-left:0px; margin-right:0px; text-align:start">1.新的安全API</h2> 有可能添加到Java EE 8中的最重要的新功能是新的安全API。这个新API的主要动机是简化,标准化和现代化跨容器和实现处理安全问题的方式。 <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">Web认证<strong>的配置</strong>已经实现了现代化,这要归功于三个使web.xml文件声明成为冗余的新注释。稍后再说。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff"><strong>新的安全上下文</strong> API标准化了servlet和EJB容器执行身份验证的方式</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff"><strong>新的Identity</strong>存储抽象简化了身份存储的使用。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">所以我们来看看这些新增的第一个。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start">注释驱动的认证机制</h3> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">此功能全部是关于配置网络安全。web.xml文件中的哪个传统所需的XML声明。</span></span></span><br />  </p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">由于<em>HttpAuthenticationMechanism</em>接口代表了HTTP身份验证,并且随附了三个内置的启用CDI的实现,这些实现代表了网络安全可以配置的三种方式之一,这已不再是必需的。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">他们触发使用这些注释之一。</span></span></span></p> <pre> <code class="language-java">@BasicAuthenticationMechanismDefinition @FormAuthenticationMechanismDefinition @CustomFormAuthenticationMechanismDefinition</code></pre> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">它们替换了servlet容器中已有的传统HTTP基本认证,基于表单和自定义表单的认证功能已经在servlet容器中了。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">例如,要启用基本身份验证,所需做的一切就是将@<em>BasicAuthenticationMechanismDefinition</em>注释添加到您的servlet,就像下面这样。</span></span></span></p> <pre> <code class="language-java">@BasicAuthenticationMechanismDefinition(realmName="${'user-realm'}") @WebServlet("/user") @DeclareRoles({ "admin", "user", "demo" }) @ServletSecurity(@HttpConstraint(rolesAllowed = "user")) public class UserServlet extends HttpServlet { //其他代码 }</code></pre> <p style="text-align:start">现在,您可以舍弃XML配置,并使用其中一个新注释来启用网络安全。<br /> <br />  </p> <h2 style="margin-left:0px; margin-right:0px; text-align:start">2. JAX-RS 2.1:新的反应客户端</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">我们来看看JAX-RS 2.1中新的被动客户端以及它如何采用反应式编程风格。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">被动方法的核心是<strong>数据流</strong>的概念,其中执行模型通过流传播更改。一个典型的例子是JAX-RS方法调用。当调用返回时,将对方法调用的结果执行下一个操作(可能是继续,完成或错误)。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">您可以将其视为<strong>异步流程</strong>的流程,下一个流程将根据前一个流程的结果进行操作,然后将流程结果传递给链中的下一个流程。数据流是<strong>可组合的,</strong>因此您可以将许多流合并并转换为一个结果。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">通过<em>调用</em>用于构造客户端实例的<em>Invocation.Builder</em>实例上的<em>rx()</em>方法来启用反应性功能。它的返回类型是<strong>具有参数化</strong><strong><em>响应</em></strong><strong>类型</strong>的<strong><em>CompletionStage</em></strong>。该<em>CompletionStage</em>接口是用Java 8中引入,并提出了一些有趣的可能性。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">例如,在这个代码片段中,两个调用是对不同的端点进行的,然后将结果合并:</span></span></span></p> <pre> <code class="language-java">CompletionStage<Response> cs1 = ClientBuilder.newClient() .target(".../books/history") .request() .rx() .get(); CompletionStage<Response> cs2 = ClientBuilder.newClient() .target(".../books/geology") .request() .rx() .get(); cs1.thenCombine(cs2, (r1, r2) -> r1.readEntity(String.class) + r2.readEntity(String.class)) .thenAccept(System.out::println);</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">3.新的JSON绑定API</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">现在我们来看看下一个伟大的功能。新的JSON绑定API,此API为<strong>JSON序列化和反序列化</strong>提供<strong>了原生Java EE解决方案</strong>。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">以前,如果您想要将JSON序列化和反序列化,则必须依赖Jackson或GSON等第三方API。不再。使用新的JSON绑定API,您可以使用本地可用的所有功能。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">从Java对象生成JSON文档并不那么简单。只需调用<em>toJson()</em>方法并将它传递给想要序列化的实例即可。</span></span></span></p> <pre> <code class="language-java">String bookJson = JsonbBuilder.create().toJson(book); </code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start">行为定制</h3> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">可以通过注释字段,JavaBean方法和类来自定义默认的序列化和反序列化行为。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">例如,您可以使用<em>@JsonbNillable</em>来自定义空处理和<em>@JsonbPropertyOrder</em>注释来自定义您在类级别指定的属性顺序。你可以指定与数字格式<em>@JsonbNumberFormat()</em>注解,并与更改字段的名称<em>@JsonbProperty()</em>注释。</span></span></span></p> <pre> <code class="language-java">@JsonbNillable @JsonbPropertyOrder(PropertyOrderStrategy.REVERSE) public class Booklet { @JsonbProperty("cost") @JsonbNumberFormat("#0.00") private Float price; }</code></pre> 或者,您可以选择使用运行时配置构建器<em>JsonbConfig</em>处理自定义: <pre> <code class="language-java">JsonbConfig jsonbConfig = new JsonbConfig() .withPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE_WITH_DASHES) .withNullValues(true) .withFormatting(true); Jsonb jsonb = JsonbBuilder.create(jsonbConfig);</code></pre> 无论哪种方式,JSON绑定API都为Java对象的序列化和反序列化提供了广泛的功能。 <h2 style="margin-left:0px; margin-right:0px; text-align:start">4. CDI 2.0:在Java SE中使用</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">现在让我们继续看下一个API。CDI 2.0 API。该版本拥有许多新功能,其中一个更有趣的功能是<strong>在Java SE应用程序中引导CDI</strong>的功能。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">要在Java SE中使用CDI,必须明确引导CDI容器。这是通过调用<strong><em>SeContainerInitializer</em></strong><strong>抽象类</strong>的<strong>静态方法  </strong><strong><em>newInstance()</em></strong><strong>来实现的</strong>。它返回一个<em>SeContainer</em>实例,该实例是CDI运行时的句柄,您可以使用该句柄执行CDI解析,如此代码片段中所示。它可以访问作为CDI核心入口点的BeanManager。</span></span></span><br />  </p> <pre> <code class="language-java">SeContainer seContainer = SeContainerInitializer.newInstance().initialize(); Greeting greeting = seContainer.select(Greeting.class).get(); greeting.printMessage("Hello World"); seContainer.close();</code></pre> 使用<em>select()</em>方法检索CDI bean,方法是传递要检索和使用的bean的类名称。 <h3 style="margin-left:0px; margin-right:0px; text-align:start">配置选项</h3> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">可以通过添加拦截器,扩展,替代方法,属性和装饰器来<strong>进一步配置</strong><em>SeContext</em>。</span></span></span></p> <pre> <code class="language-java">.enableInterceptors() .addExtensions() .selectAlternatives() .setProperties() .enableDecorators()</code></pre> 通过在<em>SeContainer</em>上调用<em>close()</em>方法手动关闭容器,或者在使用<em>Try  </em><em>-with-resources</em>结构时自动关闭容器,因为<em>SeContainer</em>  扩展了<em>AutoCloseable</em>  接口。 <h2 style="margin-left:0px; margin-right:0px; text-align:start">5. Servlet 4.0:服务器推送</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">最后但并非最不重要的一点是,Servlet 4.0中的服务器推送功能使servlet规范与HTTP / 2保持一致。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">要理解此功能,您首先需要知道服务器推送的内容。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start">什么是服务器推送?</h3> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">服务器推送是HTTP / 2协议中的许多新功能之一,旨在通过将这些资源推送到浏览器的缓存中来预测客户端资源需求,以便当客户端发送网页请求并接收到响应时从服务器,它需要的资源已经在缓存中。这是一项提高网页加载速度的性能增强功能。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start">它如何在Servlet 4.0中公开?</h3> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">在Servlet 4.0中,<strong>Server Push功能通过</strong>从<em>HttpServletRequest</em>实例获得<strong>的</strong><strong><em>PushBuilder</em></strong><strong>实例</strong><strong>公开</strong>。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">看看这段代码片段。您可以看到,通过<em>path()</em>方法在<em>PushBuilder</em>实例上设置了<em>header.png</em>的<em>路径</em>,并通过调用<em>push()</em>将其推送到客户端。当方法返回时,路径和条件头部将被清除,以便构建器重用。该<em>menu.css</em>文件推,然后<em>ajax.js</em> javascript文件推送到客户端。</span></span></span></p> <pre> <code class="language-java">protected void doGet(HttpServletRequest request, HttpServletResponse response) { PushBuilder pushBuilder = request.newPushBuilder(); pushBuilder.path("images/header.png").push(); pushBuilder.path("css/menu.css").push(); pushBuilder.path("js/ajax.js").push(); // Return JSP that requires these resources }</code></pre> 在Servlet <em>doGet()</em>方法完成执行时,资源将到达浏览器。从JSP生成的需要这些资源的HTML不需要从服务器请求它们,因为它们已经是浏览器缓存。<br />  
  • Java 8使用多个comparators进行集合分组排序

    Java 8使用多个comparators进行集合分组排序Java 8使用多个comparators进行集合分组排序
  • java 8 stream List去重/集合去重

    简介本博文主要讲解在Java 8中 如何通过stream流的方式去重简介本博文主要讲解在Java 8中 如何通过stream流的方式去重。List<String>通过stream去重List unique = list.stream().distinct().collect(Collectors.toList()); List<String>通过stream去重是非常简单的。就上面的一句代码搞定List<对象>通过stream根据集合对象的某个属性或者某些属性去重// Person 对象 public class Person { private String id; private String name; private String sex; <!--省略 get set--> } 根据name去重// 根据name去重 List<Person> unique = persons.stream().collect( Collectors.collectingAndThen( Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new) ); 根据name sex两个属性去重List<Person> unique = persons.stream().collect( Collectors. collectingAndThen( Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getName() + ";" + o.getSex()))), ArrayList::new) );
  • yum安装jdk1.8-CentOS6.5

    yum安装jdk1.8-CentOS6.5,centos6,jdk8<h2 style="text-align:left">一、yum<span style="font-family:宋体">安装</span>jdk8</h2> <h3>1.1<span style="font-family:宋体">查看当前可以安装的版本</span></h3> <p><span style="font-family:宋体">命令</span>:</p> <p>[root@localhost ~]# yum list|grep jdk</p> <p>copy-jdk-configs.noarch                      1.3-1.el6                   base  </p> <p>java-1.6.0-openjdk.x86_64                    1:1.6.0.41-1.13.13.1.el6_8  base  </p> <p>java-1.6.0-openjdk-demo.x86_64               1:1.6.0.41-1.13.13.1.el6_8  base  </p> <p>java-1.6.0-openjdk-devel.x86_64              1:1.6.0.41-1.13.13.1.el6_8  base  </p> <p>java-1.6.0-openjdk-javadoc.x86_64            1:1.6.0.41-1.13.13.1.el6_8  base  </p> <p>java-1.6.0-openjdk-src.x86_64                1:1.6.0.41-1.13.13.1.el6_8  base  </p> <p>java-1.7.0-openjdk.x86_64                    1:1.7.0.141-2.6.10.1.el6_9  updates</p> <p>java-1.7.0-openjdk-demo.x86_64               1:1.7.0.141-2.6.10.1.el6_9  updates</p> <p>java-1.7.0-openjdk-devel.x86_64              1:1.7.0.141-2.6.10.1.el6_9  updates</p> <p>java-1.7.0-openjdk-javadoc.noarch            1:1.7.0.141-2.6.10.1.el6_9  updates</p> <p>java-1.7.0-openjdk-src.x86_64                1:1.7.0.141-2.6.10.1.el6_9  updates</p> <p>java-1.8.0-openjdk.x86_64                    1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-debug.x86_64              1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-demo.x86_64               1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-demo-debug.x86_64         1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-devel.x86_64              1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-devel-debug.x86_64        1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-headless.x86_64           1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-headless-debug.x86_64     1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-javadoc.noarch            1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-javadoc-debug.noarch      1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-src.x86_64                1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-src-debug.x86_64          1:1.8.0.131-0.b11.el6_9     updates</p> <p>ldapjdk.x86_64                               4.18-8.el6                  base  </p> <p>ldapjdk-javadoc.x86_64                       4.18-8.el6                  base</p> <p> </p> <p><span style="font-family:宋体">如果没有看到上面的版本,安装</span>/<span style="font-family:宋体">更新</span>centos<span style="font-family:宋体">的扩展源</span></p> <pre> <code>#yum –y  install epel-release</code></pre> <h3>1.2<span style="font-family:宋体">安装</span>jdk1.8</h3> <p><span style="font-family:宋体">命令:</span></p> <pre> <code>[root@localhost ~]# yum install -y java-1.8.0-openjdk</code></pre> <p><img alt="可用jdk版本" class="img-thumbnail" src="/assist/images/blog/12c8939452534207b9857a8d40bb48c9.png" /></p> <h2>二、<span style="font-family:宋体">检查安装</span></h2> <p><span style="font-family:宋体">命令</span>:</p> <pre> <code>[root@localhost ~]# java –version openjdk version "1.8.0_131" OpenJDK Runtime Environment (build 1.8.0_131-b11) OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)</code></pre> <p> </p> <p><em><span style="font-family:宋体">如上显示出</span>jdk</em><em><span style="font-family:宋体">版本标示已经成功安装</span></em></p>
  • java 8 stream 多字段排序

    java 8 stream 多字段排序,本例子主要使用stream进行多个字段的排序,使用了 comparators和Comparator.thenComparing()方法。比较器之间返回一个字典排序。他的排序效果有点像SQL中的group by条件。java 8 stream 多字段排序
  • Java 8 新引入的Date 日期和time时间 使用说明

    如今,很多应用程序仍然使用API java.util.Date和java.util.CalendarAPI,包括库来使我们的生活更轻松地处理这些类型,例如JodaTime。然而,Java 8引入了新的API来处理日期和时间,这使得我们可以对日期和时间表示进行更细致的控制,向我们提供不可改变的日期时间对象,更流畅的API,并且在大多数情况下提高性能,而无需使用额外的库。我们来看看基础知识。<h2>引言</h2> <blockquote> <p>如今,很多应用程序仍然使用API <code>java.util.Date</code>和<code>java.util.Calendar</code>API,包括库来使我们的生活更轻松地处理这些类型,例如JodaTime。然而,Java 8引入了新的API来处理日期和时间,这使得我们可以对日期和时间表示进行更细致的控制,向我们提供不可改变的日期时间对象,更流畅的API,并且在大多数情况下提高性能,而无需使用额外的库。我们来看看基础知识。</p> </blockquote> <h2>LocalDate/LocalTime/LocalDateTime</h2>   <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">    让我们从以下方面最相关的新API开始<code> java.util.Date</code>:<code>LocalDate</code>日期API,代表没有时间的日期; <code>LocalTime</code>,没有日期的时间表示; 并且<code>LocalDateTime</code>,这是前两者的组合。所有这些类型都表示某个地区的本地日期和/或时间,但就像<code>java.util.Date</code>它们包含有关它所代表的区域的<strong>零</strong>信息,仅表示当前时区中的日期和时间。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">首先,下面代码这些是API支持一个简单的实例:</span></span></span><br />  </p> <pre> <code class="language-java">LocalDate date = LocalDate.of(2018,2,13); // Uses DateTimeformatter.ISO_LOCAL_DATE for which the format is: yyyy-MM-dd LocalDate date = LocalDate.parse("2018-02-13"); LocalTime time = LocalTime.of(6,30); // Uses DateTimeFormatter.ISO_LOCAL_TIME for which the format is: HH:mm[:ss[.SSSSSSSSS]] // this means that both seconds and nanoseconds may optionally be present. LocalTime time = LocalTime.parse("06:30"); LocalDateTime dateTime = LocalDateTime.of(2018,2,13,6,30); // Uses DateTimeFormatter.ISO_LOCAL_DATE_TIME for which the format is the // combination of the ISO date and time format, joined by 'T': yyyy-MM-dd'T'HH:mm[:ss[.SSSSSSSSS]] LocalDateTime dateTime = LocalDateTime.parse("2018-02-13T06:30");</code></pre> 在它们之间转换很容易: <pre> <code class="language-java">// LocalDate to LocalDateTime LocalDateTime dateTime = LocalDate.parse("2018-02-13").atTime(LocalTime.parse("06:30")); // LocalTime to LocalDateTime LocalDateTime dateTime = LocalTime.parse("06:30").atDate(LocalDate.parse("2018-02-13")); // LocalDateTime to LocalDate/LocalTime LocalDate date = LocalDateTime.parse("2018-02-13T06:30").toLocalDate(); LocalTime time = LocalDateTime.parse("2018-02-13T06:30").toLocalTime();</code></pre> 除此之外,使用“加法”和“减法”方法以及一些实用功能,对我们的日期和时间表示进行操作是非常容易的: <pre> <code class="language-java">LocalDate date = LocalDate.parse("2018-02-13").plusDays(5); LocalDate date = LocalDate.parse("2018-02-13").plus(3, ChronoUnit.MONTHS); LocalTime time = LocalTime.parse("06:30").minusMinutes(30); LocalTime time = LocalTime.parse("06:30").minus(500, ChronoUnit.MILLIS); LocalDateTime dateTime = LocalDateTime.parse("2018-02-13T06:30").plus(Duration.ofHours(2)); // using TemporalAdjusters, which implements a few useful cases: LocalDate date = LocalDate.parse("2018-02-13").with(TemporalAdjusters.lastDayOfMonth());</code></pre> 现在我们将如何<code>java.util.Date</code>转向<code>LocalDateTime</code>并且是变体?那很简单:我们可以从日期类型转换为即时类型,这是自1970年1月1日以来的时间表示,然后我们可以<code>LocalDateTime</code> 使用即时和当前区域实例化一个。 <pre> <code class="language-java">LocalDateTime dateTime = LocalDateTime.ofInstant(new Date().toInstant(), ZoneId.systemDefault());</code></pre> 要转换回日期,我们可以简单地使用Java 8时间类型表示的Instant。有一点要注意的,虽然是,虽然<code>LocalDate</code>,<code>LocalTime</code>并且<code>LocalDateTime</code>不包含任何区域或偏移信息,它们代表了一个特定区域的本地日期和/或时间,因此它们持有该区域的偏移存在。因此,我们需要提供偏移量以将特定类型正确转换为即时。<br />   <pre> <code class="language-java">// represents Wed Feb 28 23:24:43 CET 2018 Date now = new Date(); // represents 2018-02-28T23:24:43.106 LocalDateTime dateTime = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault()); // represent Wed Feb 28 23:24:43 CET 2018 Date date = Date.from(dateTime.toInstant(ZoneOffset.ofHours(1))); Date date = Date.from(dateTime.toInstant(ZoneId.systemDefault().getRules().getOffset(dateTime)));</code></pre>   <h2 style="margin-left:0px; margin-right:0px; text-align:start">时间差异 - 持续时间和周期</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">正如你已经注意到的,在上面的例子中,我们使用了一个<code>Duration</code>对象。<code>Duration</code>并且<code>Period</code>是两个日期之间的时间表示,前者表示以秒和纳秒表示的时间差,后者表示日,月和年。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">你应该什么时候使用这些?<code>Period</code>当你需要知道两个<code>LocalDate</code>表示之间的时间差异时:</span></span></span></p> <pre> <code class="language-java">Period period = Period.between(LocalDate.parse("2018-01-18"), LocalDate.parse("2018-02-14"));</code></pre> <code>Duration</code> 当你在查找包含时间信息的表示之间的区别时: <pre> <code class="language-java">Duration duration = Duration.between(LocalDateTime.parse("2018-01-18T06:30"), LocalDateTime.parse("2018-02-14T22:58"));</code></pre> 输出<code>Period</code>或<code>Duration</code>使用时<code>toString()</code>,将根据ISO-8601标准使用特殊格式。一个期间使用的模式是PnYnMnD,其中n定义了期间内存在的年数,月数或天数。这意味着P1Y2M3D定义了1年,2个月和3天的时期。。模式中的'P'是周期指示符,它告诉我们下面的格式代表一个周期。使用模式,我们也可以使用该<code>parse()</code> 方法创建基于字符串的句点。 <pre> <code class="language-java">// represents a period of 27 days Period period = Period.parse("P27D");</code></pre> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">使用时<code>Durations</code>,我们稍微离开ISO-8601标准,因为Java 8不使用相同的模式。由ISO-8601定义的模式是PnYnMnDTnHnMn.nS。这基本上<code>Period</code>是以时间表示扩展的模式。在该模式中,T是时间指示符,因此接下来的部分定义了以小时,分钟和秒为单位指定的持续时间。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">Java 8使用两种特定模式<code>Duration</code>,即在将字符串解析为a时为PnDTnHnMn.nS <code>Duration</code>,而在调用实例<code>toString()</code>上的方法时使用PTnHnMn.nS <code>Duration</code>。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">最后但并非最不重要的,我们也可以通过在类型上使用相应的方法来检索一段时间或持续时间的各个部分。但是,了解各种日期时间类型通过使用<code>ChronoUnit</code>枚举类型也支持这一点很重要。我们来看看一些例子:</span></span></span><br />  </p> <pre> <code class="language-java">// represents PT664H28M Duration duration = Duration.between(LocalDateTime.parse("2018-01-18T06:30"), LocalDateTime.parse("2018-02-14T22:58")); // returns 664 long hours = duration.toHours(); // returns 664 long hours = LocalDateTime.parse("2018-01-18T06:30").until(LocalDateTime.parse("2018-02-14T22:58"), ChronoUnit.HOURS);</code></pre>   <h2 style="margin-left:0px; margin-right:0px; text-align:start">使用区域和偏移量 - ZonedDateTime和OffsetDateTime</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">到目前为止,我们已经展示了新日期API如何使一些事情变得更容易一些。但是,真正有所作为的是在时区上下文中轻松使用日期和时间的功能。Java 8为我们提供了<code>ZonedDateTime</code>和<code>OffsetDateTime</code>,第一个是<code>LocalDateTime</code>针对特定区域(例如欧洲/巴黎)的信息,第二个是<code>LocalDateTime</code>具有偏移量的信息。有什么不同?<code>OffsetDateTime</code>使用UTC /格林威治和指定日期之间的固定时差,同时<code>ZonedDateTime</code>指定代表时间的区域,并考虑夏令时。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">转换为这两种类型都非常简单:</span></span></span><br />  </p> <pre> <code class="language-java">OffsetDateTime offsetDateTime = LocalDateTime.parse("2018-02-14T06:30").atOffset(ZoneOffset.ofHours(2)); // Uses DateTimeFormatter.ISO_OFFSET_DATE_TIME for which the default format is // ISO_LOCAL_DATE_TIME followed by the offset ("+HH:mm:ss"). OffsetDateTime offsetDateTime = OffsetDateTime.parse("2018-02-14T06:30+06:00"); ZonedDateTime zonedDateTime = LocalDateTime.parse("2018-02-14T06:30").atZone(ZoneId.of("Europe/Paris")); // Uses DateTimeFormatter.ISO_ZONED_DATE_TIME for which the default format is // ISO_OFFSET_DATE_TIME followed by the the ZoneId in square brackets. ZonedDateTime zonedDateTime = ZonedDateTime.parse("2018-02-14T06:30+08:00[Asia/Macau]"); // note that the offset does not matter in this case. // The following example will also return an offset of +08:00 ZonedDateTime zonedDateTime = ZonedDateTime.parse("2018-02-14T06:30+06:00[Asia/Macau]");</code></pre> <br /> 在切换它们时,必须记住,从a转换<code>ZonedDateTime</code>为<code>OffsetDateTime</code>将考虑夏令时,而从另一个方向转换<code>OffsetDateTime</code>为<code>ZonedDateTime</code>,意味着您不会获得有关该区域的信息,也不会在那里是适用于夏令时的任何规则。这是因为偏移不定义任何时区规则,也不会绑定到特定区域。 <pre> <code class="language-java">ZonedDateTime winter = LocalDateTime.parse("2018-01-14T06:30").atZone(ZoneId.of("Europe/Paris")); ZonedDateTime summer = LocalDateTime.parse("2018-08-14T06:30").atZone(ZoneId.of("Europe/Paris")); // offset will be +01:00 OffsetDateTime offsetDateTime = winter.toOffsetDateTime(); // offset will be +02:00 OffsetDateTime offsetDateTime = summer.toOffsetDateTime(); OffsetDateTime offsetDateTime = zonedDateTime.toOffsetDateTime(); OffsetDateTime offsetDateTime = LocalDateTime.parse("2018-02-14T06:30").atOffset(ZoneOffset.ofHours(5)); ZonedDateTime zonedDateTime = offsetDateTime.toZonedDateTime();</code></pre>   <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">如果我们不得不在这些类型之间手动转换以获得我们需要的类型,那将是一件麻烦事。这是Spring框架为我们提供帮助的地方。Spring为我们提供了很多开箱即用的日期时间转换器,这些日期转换器已<code>ConversionRegistry</code>在本<code>org.springframework.format.datetime.standard.DateTimeConverters</code>课程中注册并可在课堂上找到。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">使用这些转换器时,知道它不会在区域或偏移之间转换时间非常重要。的<code>ZonedDateTimeToLocalDateTimeConverter</code>,例如,将返回<code>LocalDateTime</code>为它指定的区域,而不是<code>LocalDateTime</code>它会代表应用程序的区域。</span></span></span><br />  </p> <pre> <code class="language-java">ZonedDateTime zonedDateTime = LocalDateTime.parse("2018-01-14T06:30").atZone(ZoneId.of("Asia/Macau")); // will represent 2018-01-14T06:30, regardless of the region your application has specified LocalDateTime localDateTime = conversionService.convert(zonedDateTime, LocalDateTime.class);</code></pre> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">最后但并非最不重要的是,您可以咨询<code>ZoneId.getAvailableZoneIds()</code>以查找所有可用时区,或使用<code>ZoneId.SHORT_IDS</code>包含几个时区(如EST,CST等)的缩略版本的地图。</span></span></span></p> <h2 style="margin-left:0px; margin-right:0px; text-align:start">格式化 - 使用 <code>DateTimeFormatter</code></h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">当然,世界各地使用不同的格式来指定时间。一个应用程序可能使用MM-dd-yyyy,而另一个应用程序使用dd / MM / yyyy。一些应用程序想要删除所有的混淆,并通过yyyy-MM-dd表示它们的日期。使用时<code>java.util.Date</code>,我们会很快转向使用多个格式化器。<code>DateTimeFormatter</code>然而,这个类为我们提供了可选的模式,因此我们可以使用单个格式化器来处理多种格式!我们来看看使用一些例子。</span></span></span><br />  </p> <pre> <code class="language-java">// Let’s say we want to convert all of patterns mentioned above. // 09-23-2018, 23/09/2018 and 2018-09-23 should all convert to the same LocalDate. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("[yyyy-MM-dd][dd/MM/yyyy][MM-dd-yyyy]"); LocalDate.parse("09-23-2018", formatter); LocalDate.parse("23/09/2018", formatter); LocalDate.parse("2018-09-23", formatter);</code></pre> 模式中的方括号定义模式中的可选部分。通过使我们的各种格式可选,与字符串匹配的第一个模式将用于转换我们的日期表示。当你使用多个模式时,这可能会很难阅读,所以我们来看看如何<code>DateTimeFormatter</code>使用builder模式创建。 <pre> <code class="language-java">DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendOptional( DateTimeFormatter.ofPattern( "yyyy-MM-dd" ) ) .optionalStart().appendPattern( "dd/MM/yyyy" ).optionalEnd() .optionalStart().appendPattern( "MM-dd-yyyy" ).optionalEnd() .toFormatter();</code></pre> <br /> 这些是包含多种模式的基础知识,但如果我们的模式仅略有不同,该怎么办?我们来看看yyyy-MM-dd和yyyy-MMM-dd。<br />   <pre> <code class="language-java">// 2018-09-23 and 2018-Sep-23 should convert to the same LocalDate. // Using the ofPattern example we’ve used above will work: DateTimeFormatter formatter = DateTimeFormatter.ofPattern("[yyyy-MM-dd][yyyy-MMM-dd]" ); LocalDate.parse( "2018-09-23", formatter ); LocalDate.parse( "2018-Sep-23", formatter ); // Using the ofPattern example where we reuse the common part of the pattern DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyy-[MM-dd][MMM-dd]" ); LocalDate.parse( "2018-09-23", formatter ); LocalDate.parse( "2018-Sep-23", formatter );</code></pre> 但是,在转换为字符串时,不应使用支持多种格式的格式化程序,因为当我们使用格式化程序将日期格式化为字符串表示形式时,它也将使用可选模式。 <pre> <code class="language-java">LocalDate date = LocalDate.parse("2018-09-23"); // will result in 2018-09-232018-Sep-23 date.format(DateTimeFormatter.ofPattern("[yyyy-MM-dd][yyyy-MMM-dd]" )); // will result in 2018-09-23Sep-23 date.format(DateTimeFormatter.ofPattern( "yyyy-[MM-dd][MMM-dd]" ));</code></pre> <br /> 自从我们进入21世纪以来,显然我们必须考虑全球化,我们希望为用户提供本地化的日期。为确保您<code>DateTimeFormatter</code>返回特定的区域设置,您可以简单地执行以下操作: <pre> <code class="language-java">DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "EEEE, MMM dd, yyyy" ).withLocale(Locale.UK); DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("yyyy-MMM-dd" ).toFormatter(Locale.UK);</code></pre> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">要查找哪些区域设置可用,您可以使用<code>Locale.getAvailableLocales()</code>。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">现在可能是您收到的日期格式比您使用的类型拥有更多的信息。<code>DateTimeFormatter</code>只要提供的日期表示不符合模式,A 就会抛出异常。让我们仔细看看这个问题以及如何解决这个问题。</span></span></span></p> <pre> <code class="language-java">// The issue: this will throw an exception. LocalDate date = LocalDate.parse("2018-02-15T13:45"); // We provide a DateTimeFormatter that can parse the given date representation. // The result will be a LocalDate holding 2018-02-15. LocalDate date = LocalDate.parse("2018-02-15T13:45", DateTimeFormatter.ISO_LOCAL_DATE_TIME);</code></pre> 我们来创建一个可以处理ISO日期,时间和日期时间模式的格式器。 <pre> <code class="language-java">DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendOptional( DateTimeFormatter.ISO_LOCAL_DATE ) .optionalStart().appendLiteral( "T" ).optionalEnd() .appendOptional( DateTimeFormatter.ISO_LOCAL_TIME ) .toFormatter();</code></pre> <br /> 现在我们可以完美地执行以下所有操作: <pre> <code class="language-java">// results in 2018-03-16 LocalDate date = LocalDate.parse( "2018-03-16T06:30", formatter ); LocalDate date = LocalDate.parse( "2018-03-16", formatter ); // results in 06:30 LocalTime time = LocalTime.parse( "2018-03-16T06:30", formatter ); LocalTime time = LocalTime.parse( "06:30", formatter ); LocalDateTime localDateTime = LocalDateTime.parse( "2018-03-16T06:30", formatter );</code></pre> 现在下一个问题在哪里?如果你试图解析一个日期模式<code>LocalDateTime</code>呢?如果你期望a <code>LocalTime</code>和你得到日期表示,反之亦然? <pre> <code class="language-java">// will throw an exception LocalDateTime localDateTime = LocalDateTime.parse("2018-03-16", formatter); LocalDate localDate = LocalDate.parse("06:30", formatter);</code></pre> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">对于最后两种情况,没有单一的正确解决方案,但这取决于您需要什么,或者这些日期和时间代表或可以代表什么。这种魔法可以在使用中找到<code>TemporalQuery</code>,您可以使用它来为模式的一部分创建默认值。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">如果我们从一开始<code>LocalDateTime</code>,而你只想要<code>LocalDate</code>或者<code>LocalTime</code>,你会收到相应的部分<code>LocalDateTime</code>。要创建一个<code>LocalDateTime</code>,我们需要它所持有的日期和时间的默认值。假设如果您没有提供关于日期的信息,我们将返回今天的日期,如果您没有提供时间,我们会假设您意味着一天的开始。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">由于我们正在返回a <code>LocalDateTime</code>,因此它不会被解析为<code>LocalDate</code>or <code>LocalTime</code>,所以让我们使用它<code>ConversionService</code>来获取正确的类型。</span></span></span></p> <pre> <code class="language-java">TemporalQuery<TemporalAccessor> myCustomQuery = new MyCustomTemporalQuery(); // results in 2018-03-16 LocalDateTime localDateTime = conversionService.convert( formatter.parse( "2018-03-16", myCustomQuery ), LocalDateTime.class ); // results in 00:00 LocalTime localTime = conversionService.convert( formatter.parse( "2018-03-16", myCustomQuery ), LocalTime.class ); class MyCustomTemporalQuery implements TemporalQuery<TemporalAccessor> { @Override public TemporalAccessor queryFrom( TemporalAccessor temporal ) { LocalDate date = temporal.isSupported( ChronoField.EPOCH_DAY ) ? LocalDate.ofEpochDay( temporal.getLong( ChronoField.EPOCH_DAY ) ) : LocalDate.now(); LocalTime time = temporal.isSupported( ChronoField.NANO_OF_DAY ) ? LocalTime.ofNanoOfDay( temporal.getLong( ChronoField.NANO_OF_DAY ) ) : LocalTime.MIN; return LocalDateTime.of( date, time ); } }</code></pre> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">使用<code>TemporalQuery</code>允许我们检查哪些信息存在并为缺失的任何信息提供默认值,使我们能够使用在我们的应用程序中合理的逻辑轻松转换为所需的类型。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">要了解如何<code>DateTimeFormatter</code>编写有效的时间模式,请查看文档。</span></span></span><br />  </p> <h2 style="margin-left:0px; margin-right:0px; text-align:start">总结</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">大多数新功能都需要一些时间来理解和习惯,Java 8 Date / Time API也不例外。新的API为我们提供了更好的访问所需的正确格式,以及使用日期时间操作的更加标准化和可读的方式。使用这些技巧和窍门,我们几乎可以涵盖我们所有的用例。</span></span></span></p>
  • idea2018配置Tomcat8热部署完整记录

    idea2018配置Tomcat8热部署完整记录    由于初步学习使用idea。所以工具用的还不是很熟。但是热部署这个东西,对于砸门开发人员来说还是非常必要的。经百度了了一下。发现真是写的参差不齐。就连百度经验里面的教程都是不全面的。导致小恼火了一把。特写一篇博客记录完整的配置方式供大家参考。<br />   <p>步骤一:添加Tomcat到idea中<br /> <img alt="添加Tomcat" class="img-thumbnail" src="/assist/images/blog/bbce7b32569f4b0580e5eef5ca5e8ef4.png" /><br /> <br /> <img alt="添加Tomcat" class="img-thumbnail" src="/assist/images/blog/48c1af1146d8474dbf456bb7d9aec17c.png" /><br /> <br /> 上图的+ -号就是添加和删除Tomcat。<br /> <br /> 步骤二:项目中Tomcat的配置<br /> <br /> 点击idea的右上角编辑配置<br /> <img alt="项目中的配置" class="img-thumbnail" src="/assist/images/blog/8c6349b680d140d78477cff1107cb80d.png" /><br /> <br /> 选择Tomcat服务器(初次则这里点击上面的+号添加Tomcat服务器),然后选择Deployment.下方有+/-号添加项目。</p> <blockquote> <p>注意添加的项目会有两个选择一个是war结尾的一个是war exploded的。选择exploded的这个非常重要。选择不对则后面无法配置</p> </blockquote> <p><br /> <img alt="添加项目包到Tomcat中" class="img-thumbnail" src="/assist/images/blog/67233e76fc504d5c9f3957d4b5a7a104.png" /><br /> <br /> <br /> 配置资源热部署<br /> <br /> 在On Update action和on frame deactivation两个配置中选择update class and resources完成配置。如果这里没看到update class and resources配置项。则检查上一步的项目部署包是否选择正确<br /> <img alt="配置资源热部署" class="img-thumbnail" src="/assist/images/blog/b650aa09dbbe4d7ca8bfd15a11eeb0f6.png" /><br /> <br /> <br /> 好啦。完整的idea2018配置Tomcat8 热部署完成。<br />  </p>
  • Java 8 字符串日期排序

    首先定义一个包含字符串日期的数据对象​public class ObjectDto implements Serializable { private static final long serialVersionUID = 858首先定义一个包含字符串日期的数据对象​public class ObjectDto implements Serializable { private static final long serialVersionUID = 8589835559483231840L; private String date;   //get set.. } 接下来初始化一些数据,并进行排序 ​​​​​​​ public static void main(String[] args){      List<ObjectDto> list = new ArrayList()<>;      ObjectDto on1 = new ObjectDto();      on1.setDate("2018-05-17");         ObjectDto on2 = new ObjectDto();         on2.seDate("2018-05-16");         ObjectDto on3 = new ObjectDto();         on3.setDate("2018-05-18");         ObjectDto on4 = new ObjectDto();         on4.setDate("2018-05-15");          list.add(on1);     list.add(on2);     list.add(on3);     list.add(on4);   //升序   List<ObjectDto> collect = list.stream().sorted(new Comparator<ObjectDto>() {       @Override       public int compare(ObjectDto o1, ObjectDto o2) {           try {               Date d1 = DateUtil.parseTime(o1.getDate(), "yyyy-MM-dd");               Date d2 = DateUtil.parseTime(o2.getDate(), "yyyy-MM-dd");                  return d1.compareTo(d2);           } catch (ParseException e) {               e.printStackTrace();           }           return 0;       }   }).collect(Collectors.toList()); }核心点在于Java 8的stream,以及内部的字符串日期转换为Date日期进行比较。 图像 小部件
  • Java8中的流Stream

    jdk8新特性流的使用<h2><strong>java 8中的流(Stream)</strong></h2> 之前因为工作原因经常需要对查询的数据库的数据集合进行筛选或者排序之类的操作,今天看了下jdk8特性,根据stream可以自动满足这些操作。 <p>流是Java API的新成员,它允许你以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现)</p> <p>Java 8中的Stream API可以让你写出这样的代码:</p> <p> 声明性——更简洁,更易读</p> <p> 可复合——更灵活</p> <p> 可并行——性能更好<br /> <br /> 首先看一下使用流和不使用流的区别,需求: 把集合中年龄小于等于20的人的名字取出来并排序<br /> 不使用流:</p> <pre> <code class="language-java">//传统JDK排序抽取数据 // 把集合中年龄小于等于20的人的名字取出来并排序 // 第一步:取年龄 <= 20的用户 List<User> tmpList = new ArrayList<>(); for (User u : list) { if (u.getAge() <= 20){ tmpList.add(u); } } // 第二步:排序 Collections.sort(tmpList, new Comparator<User>() { public int compare(User u1, User u2) { return u1.getName().compareTo(u2.getName()); } }); // 第三步 List<String> userNames = new ArrayList<>(); for(User u : tmpList){ userNames.add(u.getName()); }</code></pre> <p>jdk8流新特性<br />  </p> <pre> <code class="language-java">//JDK流新特性 //为了利用多核架构并行执行这段代码,只需要把stream()换成parallelStream(): List<String> userNames = list.stream() .filter(userJdk8 -> userJdk8.getAge() <= 20) .sorted(Comparator.comparing(User::getName)) .map(User::getName) .collect(Collectors.toList()); System.out.println(userNames.toString());</code></pre> <p> </p> <h2><strong>流与集合的区别:</strong></h2> <p>集合与流之间的差异就在于什么时候进行计算。集合是一个内存中的数据结构,它包含数据结构中目前所有的值——集合中的每个元素都得先算出来才能添加到集合中。(你可以往集合里加东西或者删东西,但是不管什么时候,集合中的每个元素都是放在内存里的,元素都得先算出来才能成为集合的一部分。)相比之下,流则是在概念上固定的数据结构(你不能添加或删除元素),其元素则是按需计算的。 从另一个角度来说,流就像是一个延迟创建的集合:只有在消费者要求的时候才会计算值。以质数为例,要是想创建一个包含所有质数的集合,那这个程序算起来就没完没了了,因为总有新的质数要算,然后把它加到集合里面。而流的话,仅仅从流中提取需要的值,而这些值——在用户看不见的地方,只会按需生成。<br /> 流只能被消费一次,如果被消费多次,则会抛出异常:</p> <pre> <code>java.lang.IllegalStateException: stream has already been operated upon or closed</code></pre> <p>如下代码所示: 这段代码的意思是遍历 lists 集合</p> <pre> <code class="language-java">List<String> lists = Arrays.asList("java8","lambda","stream"); Stream<String> stringStream = lists.stream(); Consumer<String> consumer = (x) -> System.out.println(x); stringStream.forEach(consumer); //stream has already been operated upon or closed stringStream.forEach(consumer);</code></pre> <p>之前测试类完整代码,更多stream参考<a rel="external nofollow" target="_blank" href="https://docs.oracle.com/javase/8/docs/api/">jdk8API在线文档</a>:<br />  </p> <pre> <code class="language-java">package com.yeyue; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; /** * @ClassName: JDK8Test * @Description: jdk8流的作用 此例是把集合中年龄小于等于20的人的名字取出来并排序 * @author: xiaoboLi * @date: 2017/11/22 14:32 * @Copyright: 2017 All rights reserved. */ public class JDK8Test { public static void main(String[] args) { List<User> list = new ArrayList<>(); User user = new User(11, "zhangsan", 1); list.add(user); user = new User(19, "lisi", 1); list.add(user); user = new User(10, "wanger", 0); list.add(user); user = new User(7, "wangmazi", 0); list.add(user); user = new User(25, "hanmeimei", 0); list.add(user); user = new User(30, "lilei", 0); list.add(user); //传统JDK排序抽取数据 // 把集合中年龄小于等于20的人的名字取出来并排序 // 第一步:取年龄 <= 20的用户 List<User> tmpList = new ArrayList<>(); for (User u : list) { if (u.getAge() <= 20){ tmpList.add(u); } } // 第二步:排序 Collections.sort(tmpList, new Comparator<User>() { public int compare(User u1, User u2) { return u1.getName().compareTo(u2.getName()); } }); // 第三步 List<String> userNames = new ArrayList<>(); for(User u : tmpList){ userNames.add(u.getName()); } System.out.println(userNames.toString()); //JDK流新特性 //为了利用多核架构并行执行这段代码,只需要把stream()换成parallelStream(): userNames = list.stream() .filter(userJdk8 -> userJdk8.getAge() <= 20) .sorted(Comparator.comparing(User::getName)) .map(User::getName) .collect(Collectors.toList()); System.out.println(userNames.toString()); //取小于20岁的人员信息并且根据年龄升序排序 List<User> aList = list.stream() .filter(userJdk8 -> userJdk8.getAge() <= 20) .sorted(Comparator.comparing(User::getAge)) .collect(Collectors.toList()); for (User u : aList) { System.out.println(u.getName()); } } } class User { private int age; private String name; private int sex; public User(int age, String name, int sex) { this.age = age; this.name = name; this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } }</code></pre>