-
【大赛简介】华为云求职训练营·Java实践排位赛是华为公司面向全国大学生及个人开发者举办的大型入门学习赛,帮助大家快速掌握企业及Java编程规范的要求,更好地完成学生向开发者,初级开发者向高级开发者的转变。【大赛时间】2020年9月8日09:00 ~ 2021年9月30日12:00【招募对象】高校在校大学生、个人开发爱好者(原则上要求参赛者年满18周岁)。【参与要求】以个人形式报名参加。为了大家更好地完成赛题作业,大赛设置求职训练营课程,帮助大家快速上手企业级Java编程规范。加入求职训练营,完成赛题作业!【加入训练营你将获得】1. 小白学生升级为职业开发者了解企业内部对Java编程规范的要求2. 具备入职名企的能力具备考取华为微认证的能力,考取华为企业级Java编程规范微认证3. 轻松学习快速掌握知识趣味课堂+课后作业,专家全程QQ群答疑指导【加入训练营你需要完成】 本次训练营三步走:1.点击左上角报名训练营;2.听课;3.完成26个作业。【如何参加训练营】1.报名:点击Java实践排位赛报名,或扫描下方二维码完成报名。2. 上课:点击右边链接进入课堂学习>>>企业级Java编程规范该环节课程共33节课,26个作业,每个作业题100分,总分值为2600,学习课程并完成实践作业。3.做作业:进入训练营入口,登录华为云账户,点击“作业”完成并提交。答题前建议大家先学习课程内容。注意:作业在答题截止时间前可多次提交(最多5次),系统计分以最后一次答题成绩为准。【参加大赛,享三大福利】一、官方Q群,交流学习更深入大赛交流答疑请务必加入QQ群,群里会不定时公布赛事重要信息、获奖名单、培训信息等内容。* 社群4大服务,等你解锁1. 专家答疑——作业遇难题,群内直接问专家2.班助服务——赛事答疑、作业提醒,学习每天有动力3.信息提醒——赛事信息、获奖名单信息提前知4.线上交流——同学线上交流,共同破解难题二、报名入群专享,内部公开课免费学报名并加入官方QQ群,立刻领取内部公开课三、学习奖励,知识奖品双丰收大赛设置三大奖项,完成任务,学习同时万元奖品等你拿。*{ 学霸奖 },数量有限,先到先得。参与方式及具体规则请见帖子>>>学霸奖*{ 学习激励奖 },数量有限,先到先得。参与方式及具体规则请见帖子>>>学习激励奖*{ 心得分享幸运奖 },数量有限,先到先得。参与方式及具体规则请见帖子>>>心得分享幸运奖
-
2020-11-30:java中,卡表和记忆集的区别?#福大大架构师每日一题#
-
# 视频在本帖二楼 ## 一、Spark简介 Spark是分布式批处理框架,提供分析挖掘与迭代式内存计算能力,支持多种语言(Scala/Java/Python)的应用开发。 适用以下场景: - 数据处理(Data Processing):可以用来快速处理数据,兼具容错性和可扩展性。 - 迭代计算(Iterative Computation):支持迭代计算,有效应对多步的数据处理逻辑。 - 数据挖掘(Data Mining):在海量数据基础上进行复杂的挖掘分析,可支持各种数据挖掘和机器学习算法。 - 流式处理(Streaming Processing):支持秒级延迟的流式处理,可支持多种外部数据源。 - 查询分析(Query Analysis):支持标准SQL查询分析,同时提供DSL(DataFrame), 并支持多种外部输入。 ## 二、样例背景 假定用户有某个周末网民网购停留时间的日志文本,基于某些业务要求,要求开发Spark应用程序实现如下功能: 1.统计日志文件中本周末网购停留总时间超过2个小时的女性网民信息。 2.周末两天的日志文件第一列为姓名,第二列为性别,第三列为本次停留时间,单位为分钟,分隔符为“,” log1.txt:周六网民停留日志 LiuYang,female,20 YuanJing,male,10 GuoYijun,male,5 CaiXuyu,female,50 Liyuan,male,20 FangBo,female,50 LiuYang,female,20 YuanJing,male,10 GuoYijun,male,50 CaiXuyu,female,50 FangBo,female,60 log2.txt:周日网民停留日志 LiuYang,female,20 YuanJing,male,10 CaiXuyu,female,50 FangBo,female,50 GuoYijun,male,5 CaiXuyu,female,50 Liyuan,male,20 CaiXuyu,female,50 FangBo,female,50 LiuYang,female,20 YuanJing,male,10 FangBo,female,50 GuoYijun,male,50 CaiXuyu,female,50 FangBo,female,60 ## 三、样例调试 1. 数据规划,前提:Linux环境有安装集群客户端,环境准备,参考第一课 本地新建两个文本文件input_data1.txt和input_data2.txt,将log1.txt中的内容复制保存到input_data1.txt,将log2.txt中的内容复制保存到input_data2.txt。 在HDFS客户端路径下建立一个文件夹,例如“/tmp/input”,并上传input_data1.txt,input_data2.txt到此目录,指令如下: 在HDFS客户端,执行如下命令获取安全认证,以下路径以实际hadoop客户端安装路径为准 cd /opt/hadoopclient kinit 用于认证的业务用户> 在Linux系统HDFS客户端使用命令hadoop fs -mkdir /tmp/input(hdfs dfs命令有同样的作用),创建对应目录。 进入到HDFS客户端下的“/tmp/input”目录,在Linux系统HDFS客户端使用命令hadoop fs -put input_data1.txt /tmp/input和hadoop fs -put input_data2.txt /tmp/input,上传数据文件。 2. 比对“本地时间和Linux机器时间”与集群时间误都不能超过5分钟 3. 检查linux环境的JDK版本为1.8 4. 配置linux环境的/etc/hosts文件 5. 检查 C:\Windows\System32\drivers\etc\hosts文件中是否包含所有集群节点的域名IP映射信息 6. 在IDEA打开样例代码的SparkJavaExample目录,检查SDK配置 7. 默认自动加载依赖,如未加载,则打开后选中pom.xml文件,右键点击“Add As Maven Project”后等待项目自动将依赖下载完毕 8. 在Linux环境新建目录,例如“/opt/sparktest” 9. 从Manager界面下载用户认证凭据后,解压缩获取秘钥文件user.keytab和krb5.conf,将这两个文件放到Linux环境新建的目录中例如“/opt/sparktest” 10. 修改src\main\java\com\huawei\bigdata\spark\examples\FemaleInfoCollection.java类中userPrincipal参数修改为实际用户名,userKeytabPath参数修改为user.keytab文件在linux环境的目录“/opt/sparktest/user.keytab”,krb5ConfPath参数修改为krb5.conf文件在linux环境的目录“/opt/sparktest/krb5.conf” 11. 在IDEA主页面,选择“View->Tool Windows->Maven”打开“Maven”工具窗口。 12. 在Maven工具窗口,选择clean生命周期,执行Maven构建过程。 13. 在Maven工具窗口,选择package生命周期,执行Maven构建过程。 14. 从IDEA项目目录下的target文件夹中获取到Jar包,拷贝到Spark运行环境下(即Spark客户端),如“/opt/sparktest”。 15. 进入Spark客户端目录,调用bin/spark-submit脚本运行代码,运行命令如下 ``` bin/spark-submit --class com.huawei.bigdata.spark.examples.FemaleInfoCollection --master yarn --deploy-mode client /opt/female/FemaleInfoCollection-1.0.jar <input path> ``` 其中input path,指HDFS文件系统中input的路径。 ## 四、问题互动渠道 FusonInsight 论坛入口 https://bbs.huaweicloud.com/forum/forum-1103-1.html
-
2020-11-21:java中,什么是跨代引用?#福大大#
-
在Java中可以使用HttpServer类来实现Http服务器,该类位于com.sun.net包下(rt.jar)。实现代码如下:主程序类12345678910111213141516171819202122package bg.httpserver; import com.sun.net.httpserver.HttpServer;import java.io.IOException;import java.net.InetSocketAddress;import java.util.concurrent.Executors; public class HttpServerStarter { public static void main(String[] args) throws IOException { //创建一个HttpServer实例,并绑定到指定的IP地址和端口号 HttpServer httpServer = HttpServer.create(new InetSocketAddress(8080), 0); //创建一个HttpContext,将路径为/myserver请求映射到MyHttpHandler处理器 httpServer.createContext("/myserver", new MyHttpHandler()); //设置服务器的线程池对象 httpServer.setExecutor(Executors.newFixedThreadPool(10)); //启动服务器 httpServer.start(); }}HttpServer:HttpServer主要是通过带参的create方法来创建,第一个参数InetSocketAddress表示绑定的ip地址和端口号。第二个参数为int类型,表示允许排队的最大TCP连接数,如果该值小于或等于零,则使用系统默认值。createContext:可以调用多次,表示将指定的url路径绑定到指定的HttpHandler处理器对象上,服务器接收到的所有路径请求都将通过调用给定的处理程序对象来处理。setExecutor:设置服务器的线程池对象,不设置或者设为null则表示使用start方法创建的线程。HttpHandler实现123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596package bg.httpserver; import com.sun.net.httpserver.Headers;import com.sun.net.httpserver.HttpExchange;import com.sun.net.httpserver.HttpHandler;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.OutputStream;import java.util.List;import java.util.Map;import java.util.stream.Collectors; /** * 处理/myserver路径请求的处理器类 */public class MyHttpHandler implements HttpHandler { @Override public void handle(HttpExchange httpExchange) { try { StringBuilder responseText = new StringBuilder(); responseText.append("请求方法:").append(httpExchange.getRequestMethod()).append("<br/>"); responseText.append("请求参数:").append(getRequestParam(httpExchange)).append("<br/>"); responseText.append("请求头:<br/>").append(getRequestHeader(httpExchange)); handleResponse(httpExchange, responseText.toString()); } catch (Exception ex) { ex.printStackTrace(); } } /** * 获取请求头 * @param httpExchange * @return */ private String getRequestHeader(HttpExchange httpExchange) { Headers headers = httpExchange.getRequestHeaders(); return headers.entrySet().stream() .map((Map.Entry<String, List<String>> entry) -> entry.getKey() + ":" + entry.getValue().toString()) .collect(Collectors.joining("<br/>")); } /** * 获取请求参数 * @param httpExchange * @return * @throws Exception */ private String getRequestParam(HttpExchange httpExchange) throws Exception { String paramStr = ""; if (httpExchange.getRequestMethod().equals("GET")) { //GET请求读queryString paramStr = httpExchange.getRequestURI().getQuery(); } else { //非GET请求读请求体 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpExchange.getRequestBody(), "utf-8")); StringBuilder requestBodyContent = new StringBuilder(); String line = null; while ((line = bufferedReader.readLine()) != null) { requestBodyContent.append(line); } paramStr = requestBodyContent.toString(); } return paramStr; } /** * 处理响应 * @param httpExchange * @param responsetext * @throws Exception */ private void handleResponse(HttpExchange httpExchange, String responsetext) throws Exception { //生成html StringBuilder responseContent = new StringBuilder(); responseContent.append("<html>") .append("<body>") .append(responsetext) .append("</body>") .append("</html>"); String responseContentStr = responseContent.toString(); byte[] responseContentByte = responseContentStr.getBytes("utf-8"); //设置响应头,必须在sendResponseHeaders方法之前设置! httpExchange.getResponseHeaders().add("Content-Type:", "text/html;charset=utf-8"); //设置响应码和响应体长度,必须在getResponseBody方法之前调用! httpExchange.sendResponseHeaders(200, responseContentByte.length); OutputStream out = httpExchange.getResponseBody(); out.write(responseContentByte); out.flush(); out.close(); }}运行HttpServerStarter,在浏览器中访问如下:
-
2020-11-20:java中,听说过CMS的并发预处理和并发可中断预处理吗?#福大大#
-
RTTIRTTI(RunTime Type Information)运行时类型信息,能够在程序运行时发现和使用类型信息,把我们从只能在编译期知晓类型信息并操作的局限中解脱出来传统的多态机制正是 RTTI 的基本使用:假设有一个基类 Shape 和它的三个子类 Circle、Square、Triangle,现在要把 Circle、Square、Triangle 对象放入 List<Shape> 中,在运行时,先把放入其中的所有对象都当作 Object 对象来处理,再自动将类型转换为 Shape。所有类型转换的正确性检查都是在运行时进行的,这也正是 RTTI 的含义所在:在运行时,识别一个对象的类型但这样的类型转换并不彻底,Object 只是被转型为 Shape,而不是更具体的 Circle、Square、Triangle,如果我们希望得到更具体的类型呢?比如说我们现在需要旋转所有图形,但是想跳过圆形(圆形旋转没有意义),这时可以使用 RTTI 查询某个 Shape 引用所指向对象的确切类型,然后选择进行合适的处理Class 对象众所周知,每当我们编写并编译了一个新类,就会产生一个 Class 对象,它包含了与类有关的信息。我们可以使用 Class 对象来实现 RTTI,一旦某个类的 Class 对象被载入内存,它就可以用来创建这个类的所有对象Class 对象都属于 Class 类型,既然它也是对象,那我们就可以获取和操控它的引用。forName() 是 Class 类的一个静态方法,我们可以使用 forName() 根据目标类的全限定名(包含包名)得到该类的 Class 对象。使用 forName() 会有一个副作用,那就是如果这个类没有被加载就会加载它,而在加载的过程中,Gum 类的 static 初始块会被执行。当 Class.forName() 找不到要加载的类,就会抛出异常ClassNotFoundExceptionClass gumClass = Class.forName("Gum");使用 Class.forName() 你不需要先持有这个类型的对象,但如果你已经拥有了目标类的对象,那就可以通过调用 getClass() 方法来获取 Class 引用,这个方法来自根类 Object,它将返回表示该对象实际类型的 Class 对象的引用Gum gum = new Gum();Class gumClass = gum.getClass();另外,你还可以调用 getSuperclass() 方法来得到父类的 class 对象,再用父类的 Class 对象调用该方法,重复多次,你就可以得到一个完整的类继承结构Class 对象的 newInstance() 方法可以让你在不知道一个的确切类型的时候创建这个类的对象,使用 newInstance() 来创建的类,必须带有无参数的构造器Object obj = gumClass.newInstance();当然,由于得到的是 Object 的引用,目前你只能给它发送 Object 对象能接受的调用。如果你想请求具体对象才有的调用,你就得先获取该对象的更多类型信息,并执行转型Java 还提供了另一种生成类对象的引用:类字面常量,这样做不仅更简单,而且更安全,因为它在编译时就会收到检查(不用放在 try 语句块中),而且根除了对 forName() 方法的调用,效率更高Class gumClass = Gum.class;类字面常量不仅可以用于普通类,也可以用于接口、数组以及基本数据类型。对于基本数据类型的包装类,还有一个标准字段 Type,Type 字段是一个引用,指向对应基本数据类型的 Class 对象,例如 int.class 就等价于 Integer.TYPE。还有一点值得注意的是:使用 .class 语法来获得对类对象的引用不会触发初始化到这里我们都知道了,Class 引用总是指向某个 Class 对象,而 Class 对象可以用于产生类的实例。不过自从 Java 引入泛型以后,我们就可以使用泛型对 Class 引用所指向的 Class 对象的类型进行限定,让它的类型变得更具体些Class intClass = int.class; Class<Integer> genericIntClass = int.class; intClass = genericIntClass; // 同一个东西 // genericIntClass = double.class 非法好了,既然拿到了 Class 对象,那我们就可以这个类的类型信息,常用的方法如下:方法用途asSubclass(Class clazz)把传递的类的对象转换成代表其子类的对象Cast把对象转换成代表类或是接口的对象getClassLoader()获得类的加载器getClasses()返回一个数组,数组中包含该类中所有公共类和接口类的对象getDeclaredClasses()返回一个数组,数组中包含该类中所有类和接口类的对象forName(String className)根据类名返回类的对象getName()获得类的完整路径名字newInstance()创建类的实例getPackage()获得类的包getSimpleName()获得类的名字getSuperclass()获得当前类继承的父类的名字getInterfaces()获得当前类实现的类或是接口类型转换检测到目前为止,我们已知的 RTTI 类型包括:传统的类型转换,如多态代表对象类型的 Class 对象RTTI 在 Java 中还有第三种形式,那就是关键字 instanceof,它返回一个布尔值,告诉我们对象是不是某个特定类型的实例,可以用提问的方式使用它if(x instanceof Dog) { ((Dog)x).bark(); }Java 还提供了 Class.isInstance() 方法动态检测对象类型,例如0 instance of String // 编译报错 String.class.isInstance(0) // 可以通过编译反射如果你不知道对象的确切类型,RTTI 会告诉你,但是有一个限制:必须在编译时知道类型,才能使用 RTTI 检测它。换句话说,编译器必须知道你使用的所有类看上去这并不是什么特别大的限制,但假设你引用了一个不在程序空间中的对象,比如你从磁盘文件或网络连接中获得大量的字节,并被告知这些字节代表一个类,那该怎么办呢?类 Class 支持反射的概念,java.lang.reflect 库中支持类 Field、Method、Constructor(每一个都实现了 Member 接口),这些类型的对象由 JVM 运行时创建,以表示未知类中的对应成员。通常我们不会直接使用反射,但反射可以用来支持其他 Java 特性,例如对象序列化等Field 代表类的成员变量(成员变量也称为类的属性),Class 类中定义了如下方法用来获取 Field 对象方法用途getField(String name)获得某个公有的属性对象getFields()获得所有公有的属性对象getDeclaredField(String name)获得某个属性对象getDeclaredFields()获得所有属性对象Field 类定义了如下方法设置成员变量的信息方法用途equals(Object obj)属性与 obj 相等则返回 trueget(Object obj)获得 obj 中对应的属性值set(Object obj, Object value)设置 obj 中对应属性值Method 代表类的方法,Class 类中定义了如下方法用来获取 Method 对象方法用途getMethod(String name, Class...<?> parameterTypes)获得该类某个公有的方法getMethods()获得该类所有公有的方法getDeclaredMethod(String name, Class...<?> parameterTypes)获得该类某个方法getDeclaredMethods()获得该类所有方法Method 类定义了如下方法对方法进行调用方法用途invoke(Object obj, Object... args)传递 object 对象及参数调用该对象对应的方法Constructor 代表类的构造器,Class 类中定义了如下方法用来获取 Constructor 对象方法用途getConstructor(Class...<?> parameterTypes)获得该类中与参数类型匹配的公有构造方法getConstructors()获得该类的所有公有构造方法getDeclaredConstructor(Class...<?> parameterTypes)获得该类中与参数类型匹配的构造方法getDeclaredConstructors()获得该类所有构造方法Constructor 代表类的构造方法方法用途newInstance(Object... initargs)根据传递的参数创建类的对象除了成员变量、方法和构造器以外,反射还能获取其他更多的信息,例如注解等,具体可查阅 Java API反射的强大威力大家已经看到了,通过反射我们甚至可以获取到一些“本不应该获取”的信息,例如程序员为了降低耦合,往往会使用接口来隔离组件,但反射却可以轻易破解public interface A { void f(); } class B implements A { public void f() {} public void g() {} } public class InterfaceViolation { public static void main(String[] args) { A a = new B(); a.f(); // a.g(); // 编译错误 if (a instanceof B) { B b = (B) a; b.g(); } } }通过使用 RTTI,我们发现 a 是用 B 实现的,只要将其转型为 B,我们就可以调用不在 A 中的方法。如果你不希望客户端开发者这样做,那该如何解决呢?一种解决方案是直接声明为实际类型,另一种则是让实现类只具有包访问权限,这样包外部的客户端就看不到实现类了除了这个以外,通过反射可以获得所有成员信息,包括 private 的,通常这种违反访问权限的操作并不是十恶不赦的,也许还可以帮助你解决某些特定类型的问题动态代理代理是基本的设计模式之一,一个对象封装真实对象,代替真实对象提供其他不同的操作,这些操作通常涉及到与真实对象的通信,因此代理通常充当中间对象。下面是一个简单的静态代理的示例:interface Interface { void doSomething(); } class RealObject implements Interface { @Override public void doSomething() { System.out.println("doSomething"); } } class SimpleProxy implements Interface { private Interface proxied; SimpleProxy(Interface proxied) { this.proxied = proxied; } @Override public void doSomething() { System.out.println("SimpleProxy doSomething"); proxied.doSomething(); } } class SimpleProxyDemo { public static void consumer(Interface iface) { iface.doSomething(); } public static void main(String[] args) { consumer(new RealObject()); consumer(new SimpleProxy(new RealObject())); } }当你希望将额外的操作与真实对象做分离时,代理可能会有所帮助,而 Java 的动态代理更进一步,不仅动态创建代理对象,而且可以动态地处理对代理方法的调用。在动态代理上进行的所有调用都会重定向到一个调用处理程序,该程序负责发现调用的内容并决定如何处理,下面是一个简单示例:class DynamicProxyHandler implements InvocationHandler { private Object proxied; DynamicProxyHandler(Object proxied) { this.proxied = proxied; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(proxied, args); } } class SimpleDynamicProxy { public static void consumer(Interface iface) { iface.doSomething(); } public static void main(String[] args) { RealObject real = new RealObject(); Interface proxy = (Interface) Proxy.newProxyInstance( Interface.class.getClassLoader(), new Class[]{Interface.class}, new DynamicProxyHandler(real)); consumer(proxy); } }通过调用静态方法 Proxy.newProxyInstance() 来创建动态代理,该方法需要三个参数:类加载器、希望代理实现的接口列表、以及接口 InvocationHandler 的一个实现。InvocationHandler 正是我们所说的调用处理程序,动态代理的所有调用会被重定向到调用处理程序,因此通常为调用处理程序的构造函数提供一个真实对象的引用,以便执行中间操作后可以转发请求
-
2020-11-18:java中,到底多大的对象会被直接扔到老年代?#福大大架构师每日一题#
-
案例1案例一,代码摘抄来自一企业培训材料,主要代码逻辑是打印每课成绩,并找出学生非F级别课程统计平均分数:class CourseGrade { public String title; public char grade; } public class ReportCard { public String studentName; public ArrayList<CourseGrade> cliens; public void printReport() { System.out.println("Report card for " + studentName); System.out.println("------------------------"); System.out.println("Course Title Grade"); Iterator<CourseGrade> grades = cliens.iterator(); CourseGrade grade; double avg = 0.0d; while (grades.hasNext()) { grade = grades.next(); System.out.println(grade.title + " " + grade.grade); if (!(grade.grade == 'F')) { avg = avg + grade.grade - 64; } } avg = avg / cliens.size(); System.out.println("------------------------"); System.out.println("Grade Point Average = " + avg); } }成员变量采用public,缺少数据封装性没有判断cliens是否为空,可能除以0值。注:假定它不会为空,另外逻辑可能有问题,为什么统计总分是非F课程,除数却是所有课程Size,先忽略这个问题avg这个变量多个用途,即是总分,又是平均分cliens变量名难以理解!(grade.grade == 'F') 有点反直觉while循环干了两件事,打印每课的成绩,也统计了分数培训材料并未给标准解题,尝试优化一下代码,采用Java8的Stream来简化计算过程,并对代码进行了分段:public void printReport2() { System.out.println("Report card for " + studentName); System.out.println("------------------------"); System.out.println("Course Title Grade"); cliens.forEach(it -> System.out.println(it.title + " " + it.grade)); double total = cliens.stream().filter(it -> it.grade != 'F') .mapToDouble(it -> it.grade - 64).sum(); System.out.println("------------------------"); System.out.println("Grade Point Average = " + total / cliens.size()); }进一步优化,把各类打印抽取各自函数: private void printHeader() { System.out.println("Report card for " + studentName); System.out.println("------------------------"); } private void printGrade() { System.out.println("Course Title Grade"); cliens.forEach(it -> System.out.println(it.title + " " + it.grade)); } private void printAverage() { double total = cliens.stream().filter(it -> it.grade != 'F') .mapToDouble(it -> it.grade - 64).sum(); System.out.println("------------------------"); System.out.println("Grade Point Average = " + total / cliens.size()); } public void printReport3() { printHeader(); printGrade(); printAverage(); }注:如果只算非F的平均分,可以一行搞定:double avg = cliens.stream().filter(it -> it.grade != 'F').mapToDouble(it -> it.grade - 64).average().orElse(0.0d);案例二:再看一段代码:List<Integer> tanscationsIds = transcations.parallelStream() .filter(it -> it.getType() == Transcation.GROCERY) .sorted(comparing(Transcation::getValue).resersed()) .map(Transcation::getId) .collect(Collectors::toList());代码非常清晰:过滤出类型为GROCERY的交易记录按其value值进行倒排序各自取其Id字段输出Id列表这看起来是不是像这样一条SQL语句:select t.id from tanscations t where t.type == 'GROCERY' order by t.value desc1.1 背后的知识目前Java8已广泛使用,对于Stream与Lambda应习以为常了,而不再是一种炫技。网上也有非常多的教程,若有同学还不熟悉他们的用法,可以多找找材料熟悉一下。Stream正如其名,像一条数据生产流水线,逐步叠加中间操作(算法和计算),把数据源转换为另一个数据集。笔者很早以前学过C#,接触过LINQ(Language Integrated Query),它比Java的Stream和Lambda用法更为清晰简洁,先给个简单示例:var result = db.ProScheme.OrderByDescending(p => p.rpId).Where(p => p.rpId > 10).ToList();LINQ为数据查询而生,可以算是DSL(Domain Specific Language)了,背后也是函数式编程(FP)一套理念,先记住其中两点:Monad 是一种设计模式,表示将一个运算过程,通过函数拆解成互相连接的多个步骤Lambda表达式 是一个匿名函数,Lambda表达式基于数学中的λ演算得名FP还有其它的特性:模式匹配,柯里化,偏函数,闭包,尾递归等。对FP感觉兴趣的同学不妨找找材料学习一下。现在的主流语言,都引入一些FP特性来提升语言在数据上的表达能力。C++11引入Lambda表达式,并提供<algorithm>,<functional>两个基础库,一个简单示例:int foo[] = { 10, 20, 5, 15, 25 };std::sort(foo, foo+5, [](int a,int b){return a > b;});Python提供functools库来简化一些函数式编程(还是相当的弱),一个简单示例:foo = ["A", "a", "b", "B"]sorted(foo, key=functools.cmp_to_key(locale.strcoll))2 函数式编程当然,面向对象语言中增加lambda这类特征不能就称为函数式编程了,大部分只不过是语法糖。是采用什么编程范式不在于语言的语法,而是在于思维方式。面向对象编程(OOP)在过去20多年非常成功,而函数式编程(FP)也不断地发展,他们相生相息,各自解决不同的场景问题:面向对象可以理解为是对数据的抽象,比如把一个事物抽象成一个对象,关注的是数据。函数式编程是一种过程抽象的思维,就是对当前的动作去进行抽象,关注的是动作。现实业务需求往往体现为业务活动,它是面向过程的,即先输入数据源,在一定条件下,进行一系列的交互,再输出结果。那面向过程与函数式的的区别是什么:面向过程可以理解是把做事情的动作进行分解多个步骤,所以有if/while这类语法支撑,走不同的分支步骤。函数式相比面向过程式,它更加地强调执行结果而非执行过程,利用若干个简单的执行单元让计算结果不断渐近,逐层推导复杂的运算,而不是像面向过程设计出复杂的执行过程,所以纯函数式编程语言中不需要if/while这类语法,而是模式匹配,递归调用等。面向对象的编程通过封装可变的部分来构造能够让人读懂的代码,函数式编程则是通过最大程度地减少可变的部分来构造出可让人读懂的代码。我们从Java的Stream实现也看到函数式的另一个特点:函数不维护任何状态,上下文的数据是不变的,传入的参数据处理完成之后再扔出来。结合上面的理解,我们可以先把世界事物通过OOP抽象为对象,再把事物间的联系与交互通过FP抽象为执行单元,这种结合或许是对业务活动的实现一种较好的解决方式。3 避免单一范式一提到编程范式,很容易联想到宗教的虔诚,每种宗教所表达信条都有一定合理性,但如果一直只遵循一种教条,可能也被让自己痛苦不堪。编程范式也是如此,正如Java在1.8之前是纯面向对象式,你就会觉得它非常繁琐。也如Erlang是纯函数式,你就会发现有时简单的逻辑处理会非常复杂。近些年来,由于数据分析、科学计算和并行计算的兴起,让人认识到函数式编程解决数据领域的魅力,它也越来越受欢迎。在这些领域,程序往往比较容易用数据表达式来表达,采用函数式可以用很少代码来实现。现实的业务软件,很多的逻辑其实也是对数据的处理,最简单是对数据的CURD,以及数据的组合、过滤与查询。所以函数式编程在许多语言中都得到支持,提升了对数据处理的表达能力。了解新的编程范式在适当的时候使用它们,这会使你事半功倍。无论什么编程范式,他们都是工具,在你的工具箱中,可能有锤子,螺丝刀…,这个工具在什么时候使用,取决待解决的问题。4 结语本文的案例只是一个引子,主要是想给你带来函数式编程的一些理念,函数式给我们解决业务问题提供了另一种思维方式:如何高效简洁地对数据查询与变换。许多语言都支持函数式一些能力,需要我们不断地学习,在合理的场景下使用他们。转自 csdn华为云
-
2020-11-17:java中,吞吐量优先和响应时间优先的回收器是哪些?
-
本文主要介绍的是沿Java,分布式微服务架构,大数据与流计算,Linux OS与中间件,AI,这样一套功法,来讨论从一个刚毕业的理科生,如何修炼到软件教练这个层次。以及对更高层境界的畅想。师傅领进门,修行在个人。我在本文中只指出道路,相当于一次将全套功法给你。但修行的路还请自己努力。不明白的地方,Google是个金手指。我会看大家对具体哪里更感兴趣,后续将其展开讲一下,作为一个系列。大家可以留言给我。首先第一阶段,对应炼气期。你要掌握:1, Java:俗称JAVASE。不仅仅指Java语法,还包括JDK的使用。这块知识非常沉重也非常重要。沉下心花几年时间学好它。推荐学习方式:a) 《Effective Java》。让你感受下Java里面的弯弯绕绕,并不是语法表现的那样傻白甜。b) SCJP考试。现在可能改名为OCJP了也说不定。全方位让你了解Java及里面的细节。非常重要。c) 《并发编程实践》。必读刊物。多核CPU自带L2 cache却共享内存和线程,复杂的锁,一行Java代码被编译为多行机器指令而CPU在任意机器指令间都可切换线程。面对这么复杂的硬件环境,Java是如何设计保证程序正确的。2, 敏捷开发:敏捷开发不是靠书学的(虽然也有书),而是靠实践来感悟的。就像卖油翁,不去倒油光靠看老翁写的心得,永远不会倒油。3, 算法与数据结构:a) Leetcode刷题。虽然只有极少的开发会用到算法,但这是能力的体现。不要以为就是个链表反转,至少要把动态规划级别的算法搞懂。b) 《算法导论》。读读就行了。希望你能读懂。4, 测试:要了解测试同学如何写测试用例,如何保障code coverage,如何做自动化。 当上面了解的七七八八后,你自然而然就会产生心灵上的感悟从而进阶至筑基期。你要掌握:1, 设计模式:《设计模式》,Gang Of Four。四杆老枪的设计模式(我可没开车),教会你面对各种经典场景如何构造类群。2, JVM原理:《深入理解Java虚拟机》。我刚工作时,大概06年,如果那时候有人说对JVM原理很懂,那就属于国内顶尖的技术人才了。现在知识的获取方式越来越方便了,比如阅读本文。你需要了解JVM如何使用内存,如何GC,如何调整启动参数,如何查看各种dump文件等等。3, 网络编程:书籍暂时没有推荐。反正就是要搞懂HTTP/WebSocket与TCPIP与Socket的关系等知识。4, 分布式系统中各种中间件:a) Dubbo。国内最知名开源项目。无中心化分布式架构的核心。取代了IBM的SOA产品(中心化架构造成性能瓶颈)。b) ZooKeeper。Zookeeper小红书。分布式系统数据一致性协调工具。单机进程,代码执行被认为是完全可靠的,要么执行成功要么执行失败。而到分布式系统,网络调用偏多出来一个超时。分布式系统之所以比单进程复杂那么那么多,都是这独独一个超时闹的。理解CAP,理解分布式系统数据一致性,是分布式系统不出错的保障。你从来没看见银行转账时给你少转过一分钱吧?c) Kafka。《Kafka权威指南》。要理解其为什么那么快又那么可靠又那么存储空间大。同时也是理解幂等性最方便的系统。d) Redis。《Redis设计与实现》。了解了前述的知识,Redis就是个菜。无非多了个流言协议,一致性哈希环,跳跃表,哨兵,持久化方式而已。e) MySQL(假装其也是中间件好了)。《MySQL高性能》,《MySQL技术内幕:InnoDB存储引擎》。要了解红黑树和索引的实现方式,了解innodb存储引擎的工作原理,你才能更好的理解explain sql后出来的各种回显结果,帮助你更好调优sql。MyISAM被废弃了,你可以少看一本书了,偷着乐吧,少年。f) Nginx。之所以能有多个幂等节点存在,就全靠它了。学一下它的单线程技术。明明是单线程却能做到高性能。“我就是看不上你多线程,咋啦?”唯有真正理解计算机原理才能返璞归真。g) Netty。《Netty权威指南》。你有没有感觉到在2002年后的某一年,就在短短一两年内,计算机网络突然提速了?02年JDK1.4,04年Netty。本来计算机网络性能被阻塞在IO上。但NIO大幅度提升了IO效率。Go语言为什么曾那么火?它的MPG模型还是找的IO阻塞的茬,使得多线程并发会更快。学一下Linux IO模型,零拷贝技术。理解计算机原理才能做到真正性能优化。我猜测,在JDK支持了NIO之后,Tomcat等web容器很快就进行了IO模块的更新,之后各大网站的Tomcat跟着升级,于是在全世界硬件资源没变的情况下,网络站点服务器的并发响应能力大幅提升。顺便说一句为什么Java语言会长盛不衰。因为任何新语言的特性,比如Go的MPG模型,Reactive模式等,很快就会被Java抄过来。Java已有AKKA并成功用于Flink等知名项目了。而Go想抄Java的好处,短时间很难达成。h) Flume。一个日志收集传输系统。i) ProtoBuf。序列化也是性能中需要重要关注的地方。j) Tomcat。太有名了。学学其classloader的设计。5, JAVAEE依然有用的知识:比如servlet,JMX等。哎,一个时代的落幕。6, 编译原理与操作系统:我假设你上大学时候就学过了。没有的话,至少操作系统要读一下。就读清华大学的本科教材吧。7, 分布式数据库体系架构:第4条讲的是内存网络的分布式架构。这条要讲持久化存储的分布式架构。分库分表,异构索引,数据库主备等。《数据密集型系统设计》,这本书很赞,堪称存储设计的通史。8, Spirng and Mybatis:怎么说呢,你能读懂源代码当然更好。9, 前端与CDN:至少要了解一下。10,UML建模:教会你如何认识世界并转到计算机系统里来。《UML用户指南》。 上个境界,是最难晋升的了。多少开发们被阻在这步一辈子不得前进了。因为既要承担繁重的开发任务,又要学习那么多的知识,还要处理个人的生活,太难了。这些知识对你的提升又只是相加,不是相乘的关系。熬过去后海阔天空。好了你现在是金丹期了,你的很多要继续学的知识,都是靠前面给你打基础的,你会发现你的提升曲线斜率越来越抖了。你要掌握:1, 架构设计方法论:做事要有章法。《软件架构设计》。2, 领域驱动设计:软件是真实世界在计算机中的虚拟映射。如何让软件更贴近真实世界,读一下Eric Evans的《领域驱动设计》。很晦涩,不太容易懂。3, **:**这个词现在这么火,怎能不提一下。平台是啥也许你还不清楚,那就先了解一下**。4, 高性能调优:还是那句话,真正了解计算机及runtime的本质,才能做到性能调优或Hacker。《性能之巅》。5, 稳定性建设:凑合看《逆流而上》。但是稳定性和上述的性能调优,是真正体现水平的地方。还有Google的《Google SRE》。6, 两地三中心容灾系统建设:这个目前我还不清楚有什么书。如果确实没有的话,可以趁机出一本抢占市场。7, 全链路压测:又是测试。但又不仅仅是测试。对系统的性能瓶颈节点的探查,对系统QPS的掌控。单单一个起压机就不容易设计。8, 大数据:首先,你需要跨多个领域开始了解更多的知识。其次,你会发现我对技术的介绍粒度开始越来越粗了。因为你之前打的基础 - 粗粒度之下用来支撑的细粒度知识,已经生效了。再然后就是我会减少推荐书籍。到了这里你应该形成自己的知识体系了,也就会找书了。离线海量数据存储与计算的Hadoop。将Hadoop变的更易用些的HIVE。在线海量数据存储的HBase。批计算的Spark。流计算的Flink。自成一套ELK,尤其大名鼎鼎弹性搜索。时序数据库Druid。9, 数据仓库:大数据都学了,顺便也就把数仓学了呗。顺手的事而已。10,IC:HCIE,这个我就不班门弄斧了。11,网络安全:我也不懂。汗。12,Linux OS。可不仅仅是使用命令操作系统而已。当然,即使是这样也不容易了。当你还要再继续晋升,就涉及到我也不完全理解的境界了。1, 中间件的实现细节:作为业务侧的技术架构师,通常会把存储和网络的需求下压给中间件团队。但是他们是怎么实现的呢?细节重要的点是什么?2, 使用Master Slave模式,Spark等是如何实现分布式任务分解并确保计算正确的?3, Docker虚拟化技术。4, Yarn的资源分配技术。5, 计算机网络等。6, 再扩展一下技术领域,触角伸到AI领域。那么数学基础,各种论文与算法实现。又或者使用算法来赋能某个具体的业务领域比如AI赋能新零售。7, 也可以往IOT方向发展。随着5G的发展,这个应该也很火。持续看好。
-
大家介绍Javaweb连接Mysql数据库步骤方法及其实例,主要包括Javaweb中mysql数据库连接步骤方法及其实例使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,如有不妥之处请大佬指正!先来说说jdbc的概念JDBCJava数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法 准备工作IntelliJ IDEA mysql-connector-java-5.0.8-bin(不是最新版本)建立数据库 建表 下面说说具体的实现方法 一、直接连接主要步骤:先导包:mysql-connector-java-5.0.8-bin.jar,放在WebRoot/WEB-INF/lib/下 1.加载驱动//com.MySQL.jdbc.Driver2.获取连接 Connection对象3.获取用于向数据库发送SQL的Statement对象4.执行sql,获取数据,解析数据5.关闭连接,释放资源/*协议:子协议://主机:端口/数据库名*/ Stringurl="jdbc:mysql://localhost:3306/jdbctest"; //mysql数据库的用户名与密码,安装时自己设置,一般默认为root Stringuser="root"; Strin**word="root"; Connectionconnection=null; Statementstatement=null; ResultSetresultSet=null; try{ //1.加载驱动//com.mysql.jdbc.Driver /* *DriverManager.registerDriver(new *Driver());用这种方法会加载两次驱动,也就是说会创建两个drive对象 */ Class.forName("com.mysql.jdbc.Driver"); //2.获取连接 connection=DriverManager.getConnection(url,user,password); //3.获取用于向数据库发送SQL的Statement对象 statement=connection.createStatement(); //4.执行sql,获取数据 resultSet=statement.executeQuery("SELECT*FROMusers;"); //解析数据 while(resultSet.next()){ intid=resultSet.getInt("id"); Stringname=resultSet.getString("name"); Stringpsd=resultSet.getString("password"); Stringemail=resultSet.getString("email"); Stringbirthday=resultSet.getString("birthday"); System.out.println(id+""+name+""+psd+""+email +""+birthday); } }catch(ClassNotFoundExceptione){ e.printStackTrace(); }catch(SQLExceptione){ e.printStackTrace(); }finally{ //5.关闭连接,释放资源 if(resultSet!=null){ try{ resultSet.close(); }catch(SQLExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } resultSet=null; } if(statement!=null){ try{ statement.close(); }catch(SQLExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } statement=null; } if(connection!=null){ try{ connection.close(); }catch(SQLExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } connection=null; } /* 协议:子协议://主机:端口/数据库名 */ String url = "jdbc:mysql://localhost:3306/jdbctest"; // mysql数据库的用户名与密码,安装时自己设置,一般默认为root String user = "root"; String password = "root"; Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { // 1.加载驱动//com.mysql.jdbc.Driver /* * DriverManager.registerDriver(new * Driver());用这种方法会加载两次驱动,也就是说会创建两个drive对象 */ Class.forName("com.mysql.jdbc.Driver"); // 2.获取连接 connection = DriverManager.getConnection(url, user, password); // 3.获取用于向数据库发送SQL的Statement对象 statement = connection.createStatement(); // 4.执行sql,获取数据 resultSet = statement.executeQuery("SELECT * FROM users;"); // 解析数据 while (resultSet.next()) { int id = resultSet.getInt("id"); String name = resultSet.getString("name"); String psd = resultSet.getString("password"); String email = resultSet.getString("email"); String birthday = resultSet.getString("birthday"); System.out.println(id + " " + name + " " + psd + " " + email + " " + birthday); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //5.关闭连接,释放资源 if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } resultSet = null; } if (statement != null) { try { statement.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } statement = null; } if (connection != null) { try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } connection = null; } }二、将数据库连接封装成一个工具类这样做的好处是,在实际开发中,就能做到,改一处即可修改全局。1.建一个名为db.properties的配置文件,放于src/url=jdbc:mysql://localhost:3306/jdbctest username=root password=root driver=com.mysql.jdbc.Driver2.工具类:importjava.io.IOException; importjava.sql.Connection; importjava.sql.DriverManager; importjava.sql.ResultSet; importjava.sql.SQLException; importjava.sql.Statement; importjava.util.Properties; publicclassJdbcUtil{ //私有静态变量,用以读取配置文件 privatestaticPropertiesconfig=newProperties(); static{ try{ //配置资源文件 config.load(JdbcUtil.class.getClassLoader().getResourceAsStream("db.properties")); //加载驱动 Class.forName(config.getProperty("driver")); }catch(IOExceptione){ e.printStackTrace(); }catch(ClassNotFoundExceptione){ e.printStackTrace(); } } publicstaticConnectiongetConnection(){ Connectionconnection=null; try{ connection=DriverManager.getConnection(config.getProperty("url"),config.getProperty("username"),config.getProperty("password")); }catch(SQLExceptione){ e.printStackTrace(); } returnconnection; } //用以关闭连接,释放资源 publicstaticvoidreleaseConn(Connectionconnection,Statementstatement, ResultSetresultSet){ if(resultSet!=null){ try{ resultSet.close(); }catch(SQLExceptione){ e.printStackTrace(); } resultSet=null; } if(statement!=null){ try{ statement.close(); }catch(SQLExceptione){ e.printStackTrace(); } statement=null; } if(connection!=null){ try{ connection.close(); }catch(SQLExceptione){ e.printStackTrace(); } connection=null; } } }3.使用实例:Connectionconnection=null; Statementstatement=null; ResultSetresultSet=null; try{ //调用工具类中的静态方法来获取连接 connection=JdbcUtil.getConnection(); statement=connection.createStatement(); resultSet=statement.executeQuery("select*fromusers"); while(resultSet.next()){ intid=resultSet.getInt("id"); Stringname=resultSet.getString("name"); Stringpsd=resultSet.getString("password"); Stringemail=resultSet.getString("email"); Stringbirthday=resultSet.getString("birthday"); System.out.println(id+""+name+""+psd+""+email +""+birthday); } }catch(Exceptione){ e.printStackTrace(); }finally{ //调用工具类中的静态方法来关闭连接,释放资源 JdbcUtil.releaseConn(connection,statement,resultSet); }每行代码都有注释,欢迎大佬提出问题哈!书山有路勤为径,学海无涯苦作舟!
-
1.首先要导入json相关的jar包引入的jar包:(版本自行定义,可以选用使用人数偏多的版本,这样比较稳定)commons-beanutils-1.9.2.jarcommons-collections-3.2.1.jarcommons-lang-2.6.jarcommons-logging-1.2.jarezmorph-1.0.6.jarjson-lib-2.4-jdk15.jarjar包的下载可以去下面这个网址搜索:https://mvnrepository.com/2.在Eclipse下(也可以是IntelliJ IDEA或者MyEclipse)新建package和Class(步骤略过,可自行选择名字),这里就使用jsonTest。以下代码块方法见注释,是将JSONObject转换为HashMap的主要方法,传入参数为一个JSONObject对象,返还值为一个HashMap。123456789101112//1.將JSONObject對象轉換為HashMap<String,String>public static HashMap<String, String> JsonObjectToHashMap(JSONObject jsonObj){ HashMap<String, String> data = new HashMap<String, String>(); Iterator it = jsonObj.keys(); while(it.hasNext()){ String key = String.valueOf(it.next().toString()); String value = (String)jsonObj.get(key).toString(); data.put(key, value); } System.out.println(data); return data;}这个方法是将JSON字符串转换为HashMap,传入参数为一段json格式的字符串,返还一个HashMap。12345678910111213141516171819202122//2.将json字符串转换成HashMap<String,String>public static HashMap<String, String> JsonToHashMap(String JsonStrin){ HashMap<String, String> data = new HashMap<String, String>(); try{ // 将json字符串转换成jsonObject JSONObject jsonObject = JSONObject.fromObject(JsonStrin); @SuppressWarnings("rawtypes") Iterator it = jsonObject.keys(); // 遍历jsonObject数据,添加到Map对象 while (it.hasNext()) { String key = String.valueOf(it.next()).toString(); String value = (String) jsonObject.get(key).toString(); data.put(key, value); } }catch (Exception e) { e.printStackTrace(); //JOptionPane.showMessageDialog(null,"ERROR:["+e+"]"); } System.out.println(data); return data; } 在这里顺便介绍一下Iterator类(迭代器)迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。 Java中的Iterator功能比较简单,并且只能单向移动: (1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。 (2) 使用next()获得序列中的下一个元素。 (3) 使用hasNext()检查序列中是否还有元素。 (4) 使用remove()将迭代器新返回的元素删除。 Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。3.直接上代码12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758package JSON; import java.util.HashMap;import java.util.Iterator;import net.sf.json.JSONObject; public class JsonTest { public static void main(String[] args) { JSONObject jsonObj = new JSONObject(true); String content1 = "aaaaa"; String content2 = "bbbbb"; String content3 = "ccccc"; jsonObj.put("a", content1); jsonObj.put("b", content2); jsonObj.put("c", content3); System.out.println(jsonObj.toString()); JsonObjectToHashMap(jsonObj); String jsonstr = "{name:'王杨',sex:'男',school:'郑州航空工业管理学院'}"; JsonToHashMap(jsonstr); } //1.將JSONObject對象轉換為HashMap<String,String> public static HashMap<String, String> JsonObjectToHashMap(JSONObject jsonObj){ HashMap<String, String> data = new HashMap<String, String>(); Iterator it = jsonObj.keys(); while(it.hasNext()){ String key = String.valueOf(it.next().toString()); String value = (String)jsonObj.get(key).toString(); data.put(key, value); } System.out.println(data); return data; } //2.将json字符串转换成HashMap<String,String> public static HashMap<String, String> JsonToHashMap(String JsonStrin){ HashMap<String, String> data = new HashMap<String, String>(); try{ // 将json字符串转换成jsonObject JSONObject jsonObject = JSONObject.fromObject(JsonStrin); @SuppressWarnings("rawtypes") Iterator it = jsonObject.keys(); // 遍历jsonObject数据,添加到Map对象 while (it.hasNext()) { String key = String.valueOf(it.next()).toString(); String value = (String) jsonObject.get(key).toString(); data.put(key, value); } }catch (Exception e) { e.printStackTrace(); //JOptionPane.showMessageDialog(null,"ERROR:["+e+"]"); } System.out.println(data); return data; } }记得修改自己的package名称和 class名称。4.调用main方法测试(1)传入参数为JSONObject:输出结果为:(2)传入参数为JSON字符串:输出结果为:这里可以看到,输出的参数顺序和传入时正好相反。但是输出类型为HashMap,数据存储的格式是以key-value键值对的形式存数于HashMap中的。我们可以通过获取key值来获取到其对应的value。增加如下代码在main方法最后面:123456System.out.println("");//空格换行//通过对应的key键值,获取valueHashMap<String,String> hashmap = JsonToHashMap(jsonstr);System.out.println("--------通过遍历HashMap输出值:-------");System.out.println("name:"+hashmap.get("name")+",sex:"+hashmap.get("sex")+",school:"+hashmap.get("school"));得到如下结果:结语:到此基本的方法介绍完毕,其实是依靠了JSONObject这个对象的fromObject()方法。fromObject()方法可以转换的类型很多,可以是map、list、数组等等。运用在自己的项目中时,可以是bean或者model等自定义的类。1234567891011121314151617181920211. List集合转换成json代码List list = new ArrayList();list.add( "first" );list.add( "second" );JSONArray jsonArray2 = JSONArray.fromObject( list ); 2. Map集合转换成json代码Map map = new HashMap();map.put("name", "json");map.put("bool", Boolean.TRUE);map.put("int", new Integer(1));map.put("arr", new String[] { "a", "b" });map.put("func", "function(i){ return this.arr[i]; }");JSONObject json = JSONObject.fromObject(map); 3. Bean转换成json代码JSONObject jsonObject = JSONObject.fromObject(new JsonBean()); 4. 数组转换成json代码boolean[] boolArray = new boolean[] { true, false, true };JSONArray jsonArray1 = JSONArray.fromObject(boolArray);以上类型均可以借用fromObject()方法转换为一个JSONObject类型实例。json作为轻量级的数据格式,在前后端数据交互时很常见,每个公司应该都有自己的JSON转换方法,是公司常见的工具类。方便了随后的开发使用。
-
一、配置tomcat 在tomcat的catalina.sh文件开头加上如下配置:JAVA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.184.129 -Dcom.sun.management.jmxremote.rmi.port=9999" 各参数含义: -Dcom.sun.management.jmxremote:是否支持远程JMX访问,默认true; -Dcom.sun.management.jmxremote.port:是JMX远程监控端口号,需要在防火墙开放该端口; -Dcom.sun.management.jmxremote.ssl=false:表示是否对连接开启SSL加密,默认开启; -Dcom.sun.management.jmxremote.authenticate=false :是否需要开启用户认证,默认开启,如果开启需要额外配置授权文件; -Djava.rmi.server.hostname=192.168.184.129:远程服务器的主机名; -Dcom.sun.management.jmxremote.rmi.port=9999:RMI端口号,JMX在远程连接时,会随机开启一个RMI端口作为连接的数据端口,可以和JMX端口号相同。二、配置主机名 使用hostname -i命令查看主机名是否为外网访问ip192.168.184.129:[root@localhost bin]# hostname -i127.0.0.1 127.0.0.1 发现是127.0.0.1,所以需要修改主机名为192.168.184.129。(1)修改/etc/sysconfig/network文件 原文件内容为:[root@localhost bin]# cat /etc/sysconfig/networkNETWORKING=yesHOSTNAME=localhost.localdomain 修改HOSTNAME为192.168.184.129,即修改后内容为:[root@localhost bin]# cat /etc/sysconfig/networkNETWORKING=yesHOSTNAME=192.168.184.129 修改后使用service network restart命令重启网络服务。(2)修改/etc/hosts文件 原文件内容为:[root@localhost bin]# cat /etc/hosts127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 修改127.0.0.1为192.168.184.129,并删除第二行ipv6的配置,即修改后文件内容为:[root@localhost bin]# cat /etc/hosts192.168.184.129 localhost localhost.localdomain localhost4 localhost4.localdomain4 此时使用hostname -i命令再次查看主机名,已经修改过来了[root@localhost bin]# hostname -i192.168.184.129三、配置防火墙 配置防火墙开放9999端口,编辑/etc/sysconfig/iptables文件,加入-A INPUT -m state --state NEW -m tcp -p tcp --dport 9999 -j ACCEPT,然后service iptables restart重启防火墙服务。四、配置jvisualvm 启动tomcat后,在windows本地jdk安装路径bin目录下找到jvisualvm.exe,双击打开后左侧显示如下:在“远程”上右键-->添加远程主机-->填写主机名:点击确定后,远程选项下多了一条刚才添加的主机列表。右键-->添加JMX连接,如下图,填入JMX远程连接端口号9999,并勾选“不要求ssl连接”:点击确定后,左侧多了一条pid为6822的远程连接,6822是远程tomcat的pid:双击该连接,在右侧可以动态查看jvm的概览信息,监控CPU,java堆,元空间,类,线程等数据:五、常见问题 在添加JMX连接的时候,经常会出现如下报错:此时可以从以下几个方向检查:(1)检查tomcat应用是否启动,或者修改tomcat配置后是否重启tomcat,确保9999端口处于监听状态,查看命令netstat -nl|grep 9999;(2)检查主机名是否和tomcat中配置的主机名相同,如果不同则按照第二步修改主机名;(3)检查RMI端口号端口号是否在防火墙进行了配置,如果配置的RMI端口号和JMX端口号不一致,需要在防火墙配置RMI端口号允许访问,如果没有配置,则添加-Dcom.sun.management.jmxremote.rmi.port=9999配置RMI端口号
-
2020-11-12:java中as-if-serial语义和happen-before语义有什么区别?#福大大架构师每日一题#
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签