首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

【Android学习笔记】Android Studio简单断点调试

首先点击断点调试按钮运行App 启动之后,会弹出如下图的提示框,不要管,几秒之后这个弹框会自动消失,然后App会成功运行。 下面介绍一下断点调试的相关操作按钮对应的功能: 按钮1的功能:从当前断点跳到下一个断点,如果当前断点为最后一个断点则点击后断点结束,App正常运行。 按钮2(step over)的功能:一步步往下走,及按代码逻辑一行一行代码往下走。 按钮3(step into)的功能:遇到方法就往方法里走。 按钮4(force step into )的功能:所有方法看完整,即可以看到你所调用的所有方法的实现会让你跟着它走一遍。 按钮5(step out )的功能:有断点下一个,走完断点继续走,断点走完之后会一直往下跳,无法结束断点而让App正常运行。 按钮6(run to Cursor)的功能:下个断点我们见,同按钮1的功能。 按钮7的功能:停止App的运行。

优秀的个人博客,低调大师

day09_request&response学习笔记

============================================================ 一、HttpServletResponse接口 学好HttpServletResponse与HttpServletRequest的关键是:理解HTTP协议。 Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。 (注意:request和response分别表示的是对象名,实际上不是对象) request和response对象既然代表请求和响应, 那我们要获取客户端提交过来的数据,只需要找request对象就行了。 要向容器(服务器)输出数据,只需要找response对象就行了。 因为每一的请求都会调用一次service(request,response)方法。 方法的形参request和response是由服务器创建的,在service执行之前就已经创建好了,分别是两个对象(是不需要new的,服务器帮你干了)。 1、响应消息行HTTP/1.1200OK HTTP/1.1 200 OK 协议/版本 响应状态码 对响应码的描述(一切正常) HttpServletResponse接口的方法: void setStatus(intsc)设置响应状态码 response.setStatus(302); response.setHeader("location", "url"); // 上面两句代码等价于下面一句 response .sendRedirect("location"); Location:http://www.it315.org/index.jsp 指示新的资源的位置通常和302/307一起使用,完成请求重定向 请求转发和请求重定向图解: 2、响应消息头 HttpServletResponse接口的方法: void sendRedirect(Stringlocation)请求重定向 void setHeader(Stringname,Stringvalue)设置响应消息头信息 // 设置客户端(浏览器)使用什么编码(通过响应消息头设置) response.setHeader("content-type","text/html; charset=UTF-8"); //告知客户端不缓存 response.setHeader("pragma","no-cache"); response.setHeader("cache-control","no-cache"); response.setDateHeader("expires",0); Referesh 刷新 3、响应正文(主体) ServletResponse接口的方法: PrintWriter getWriter() 获取字符输出流 ServletOutputStream getOutputStream() 获取字节输出流 void setCharacterEncoding(Stringcharset) 设置服务器使用什么编码 String setContentType(Stringtype) 设置将发送到客户端的响应的内容类型(同时设置客户端和服务端要使用的编码) 例如: response.setContentType("text/html;charset=UTF-8"); URLEncoder是HTML格式编码的实用工具类,该类包含了将String转换为application/x-www-form-urlencodedMIME格式的静态方法。 案例1:向客户端输出中文数据:用PrintWriter(字符流)发送数据 案例2:向客户端输出中文数据:用OutputStream(字节流)发送数据 案例3:客户端下载文件 案例4:自己编写代码实现客户端网页显示验证码 案例5:通过验证码工具类实现客户端网页显示验证码 案例6:实现定时刷新 4、response的几处细节 1. getOutputStream和getWriter方法分别用于得到输出二进制数据、输出文本数据的ServletOuputStream、Printwriter对象。 2. getOutputStream和getWriter这两个方法 互相排斥 ,调用了其中的任何一个方法后,就不能再调用另一方法。否则会抛异常。 3. Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取, Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头 组合 后输出到客户端。 4. Serlvet的service方法结束后,Servlet引擎将检查getOutputStream或getWriter方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象。 ( 注:这里的Servlet引擎就是Tomcat服务器 ) ============================================================ 二、HttpServletRequest 1、请求消息行 Get http://localhost:8080/ day09_01_HttpServletRequest /servlet/req1 ? username=zs&pwd=123 HTTP/1.1 HttpServletRequest接口的方法: String getMethod() 获取请求行的请求方式 StringgetRequestURL() 返回客户端发出请求时的完整 URL StringgetRequestURI() 返回请求消息行中的资源名部分(8080之后所有的) StringgetContextPath() 获取当前应用的虚拟目录 例如:/day09_01_HttpServletRequest String getQueryString() 返回请求消息行中的参数部分 2、请求消息头 HttpServletRequest接口的方法: String getHeader(Stringname) 根据头名称得到头信息值 Enumeration getHeaderNames() 获取 所有请求消息头的 name Enumeration getHeaders(Stringname) 获取 相同请求消息头名称的信息值 1 package com.itheima.servlet; 2 3 import java.beans.IntrospectionException; 4 import java.beans.PropertyDescriptor; 5 import java.io.IOException; 6 import java.io.UnsupportedEncodingException; 7 import java.lang.reflect.InvocationTargetException; 8 import java.lang.reflect.Method; 9 import java.util.Enumeration; 10 import java.util.Map; 11 12 import javax.servlet.ServletException; 13 import javax.servlet.http.HttpServlet; 14 import javax.servlet.http.HttpServletRequest; 15 import javax.servlet.http.HttpServletResponse; 16 17 import org.apache.commons.beanutils.BeanUtils; 18 19 import com.itheima.entity.User; 20 21 public class ServletDemo3 extends HttpServlet { 22 23 public void doGet(HttpServletRequest request, HttpServletResponse response) 24 throws ServletException, IOException { 25 // 告诉服务器要使用什么码表,注:客户端浏览器使用的是什么码表,传过来给服务器的就该使用什么码表 26 request.setCharacterEncoding("UTF-8"); // 注:只能处理post请求方式 27 28 test1(request); 29 test2(request); 30 test3(request); 31 test4(request); 32 } 33 34 private void test4(HttpServletRequest request) { 35 try { 36 User u = new User(); 37 System.out.println("封装数据前:" + u); 38 39 BeanUtils.populate(u, request.getParameterMap()); 40 41 System.out.println("封装数据后:" + u); 42 } catch (Exception e) { 43 e.printStackTrace(); 44 } 45 } 46 47 private void test3(HttpServletRequest request) { 48 try { 49 User u = new User(); 50 System.out.println("封装数据前:" + u); 51 // 获取表单数据 52 Map<String, String[]> map = request.getParameterMap(); 53 54 for (Map.Entry<String, String[]> m : map.entrySet()) { 55 String name = m.getKey(); 56 String[] value = m.getValue(); 57 58 // 反射 59 // 创建一个属性描述器对象 60 PropertyDescriptor pd = new PropertyDescriptor(name, User.class); 61 // 得到setter属性对象 62 Method setter = pd.getWriteMethod(); 63 64 if (value.length == 1) { 65 setter.invoke(u, value[0]); // 给只有一个值的变量赋值 66 } else { 67 setter.invoke(u, (Object) value); // 给复选框赋值 68 } 69 } 70 71 System.out.println("封装数据后:" + u); 72 73 } catch (Exception e) { 74 e.printStackTrace(); 75 } 76 } 77 78 private void test2(HttpServletRequest request) { 79 // 获取表单提交的所有的name的名称 80 Enumeration names = request.getParameterNames(); 81 while (names.hasMoreElements()) { 82 String name = (String) names.nextElement(); // 得到每一个name名称 83 String[] values = request.getParameterValues(name); // 根据name名称,得到value值 84 for (int i = 0; values != null && i < values.length; i++) { 85 System.out.println(name + "\t" + values[i]); 86 } 87 } 88 } 89 90 private void test1(HttpServletRequest request) throws UnsupportedEncodingException { 91 // 获取表单数据 92 // 根据表单中name属性的名,获取value属性的值方法 93 String username = request.getParameter("username"); 94 String pwd = request.getParameter("pwd"); 95 String sex = request.getParameter("sex"); 96 String[] hobbys = request.getParameterValues("hobby"); 97 String city = request.getParameter("city"); 98 99 // 解决get方式编码 100 username = new String(username.getBytes("iso-8859-1"), "UTF-8"); 101 102 System.out.println(username); 103 System.out.println(pwd); 104 System.out.println(sex); 105 106 for (int i = 0; hobbys != null && i < hobbys.length; i++) { 107 System.out.print(hobbys[i] + "\t"); 108 } 109 System.out.println(); 110 111 System.out.println(city); 112 } 113 114 public void doPost(HttpServletRequest request, HttpServletResponse response) 115 throws ServletException, IOException { 116 doGet(request, response); 117 } 118 119 } 3、请求正文(重要) 与获取表单数据相关的方法: <inputtype="text"name="username"/> ServletRequest接口的方法: String getParameter(Stringname) 根据表单中 name 属性的名,获取 value 属性的值 String[] getParameterValues( Stringname) 专为复选框获取值提供的方法 EnumerationgetParameterNames() 获取 表单提交的所有的 name名 Map getParameterMap() 获取 表单提交的所有value值 ( 做框架时用,非常实用) ServletInputStream getInputStream 以字节流的方式得到所有表单数据 与操作非表单数据相关的方法:(request也是一个域对象,也维护了一个Map集合,只是作用的范围较小,在当前请求范围内有效) ServletRequest接口的方法: voidsetAttribute(Stringname,Objectvalue) ObjectgetAttribute(Stringname) voidremoveAttribute(Stringname) 与请求转发相关的方法: ServletRequest接口的方法: // 得到请求转发或请求包含的协助对象 RequestDispatchergetRequestDispatcher(Stringpath) RequestDispatcher接口的方法: void forward(ServletRequestrequest,ServletResponseresponse)// 转发的方法 void include(ServletRequestrequest,ServletResponseresponse)// 请求包含 与请求编码相关的方法: ServletRequest接口的方法: //解决post提交方式的编码 request.setCharacterEncoding("UTF-8");// 告诉服务器要使用什么码表,注: 只能处理 post 请求方式 // 解决 get提交 方式的编码(需要一个一个变量的转换,麻烦,用的不多,一般用在地址栏上明文写的链接上,因为明文是get方式提交) Stringname=newString(name.getBytes(" iso-8859-1" ), " UTF-8" ); 注:一般而言,默认是get提交方式,所以我们在写表单的html代码时,要立即把表单的属性method="post" 最好。 request与response对象解决乱码的应用: ============================================================ 我的GitHub地址: https://github.com/heizemingjun 我的博客园地址: http://www.cnblogs.com/chenmingjun 我的蚂蚁笔记博客地址: http://blog.leanote.com/chenmingjun Copyright ©2018 黑泽明军 【转载文章务必保留出处和署名,谢谢!】

优秀的个人博客,低调大师

java学习笔记--常用集合和迭代器

终于静下心来写这篇博客来谈谈我对集合的理解了。本来想是早点推的,结果发现还是不愿动手敲这一篇说明。想想当初学集合也算是有点小焦躁,一个toArray函数把我搞死了一天也攻不下来,又是看源码 (native真烦)又是google的,也算是有点成果。接下里进入正题吧 先来谈谈数组 先看下面这个栗子: int[] cur=new int[10]; 发现问题没? 数组被定长度了,如果我们一开始定义了这么一个数组,那么我们后期加入其他数值怎么办,报一个数组越界的bug 就GG。 这个时候集合就出来了 还是来看一下栗子: ArrayList arrayList3=new ArrayList(); ArrayList<String> arrayList1=new ArrayList<String>(); ArrayList<Integer> arrayList2=new ArrayList<Integer>(); 第一个栗子:定义了一个集合 可接受任意数值 第二个栗子:定义了一个数组 接受String类型数值 第二个栗子:定义了一个数组 接受Integer类型数值 我们可以得出这个结论: 集合:集合是存储对象数据的集合容器。 集合比数组的优势: 1. 集合可以存储任意类型的对象数据,数组只能存储同一种数据类型 的数据。 2. 集合的长度是会发生变化的,数组的长度是固定的。 注意:集合重只能存储对象 不能存储基本类型 意思就是集合泛型不能定义为int ArrayList<int> arrayList1=new ArrayList<int>(); 编译器会报错 介绍根接口Collection前 先来看看Collection 和 Collections的区别: Collection 和Collections是两个不同的概念。Collection是一个接口,所有的集合类(除Map外)都要继承(实现)该接口。它提供了对集合对象进行基本操作的通用接口方法。Collections是一个包装类,它包含有各种有关集合操作的静态多态方法。(Collections是一个工具类,不能实例化) 先来看一下 关系图: 是不是看晕了 那么多类 其实平常用到的也就那么几个类 和 接下来我只介绍有序可重复排列的集合(List) 无序不可重复排序的集合(Set)和键值对的集合(Map) 先来看一下原始的根接口Collection的常用方法吧 Collection接口中的方法: 增加 add(E e) 添加成功返回true,添加 失败返回false. addAll(Collection c) 把一个集合 的元素添加到另外一个集合中去。 删除 clear() remove(Object o) removeAll(Collection c) retainAll(Collection c) 查看 size() 判断 isEmpty() contains(Object o) containsAll(Collection<?> c) 迭代 toArray() iterator() 举个栗子: Collection c = new ArrayList(); c.add("令计划"); //创建集合 Collection c2 = new ArrayList(); c2.add("xx"); c.addAll(c2); // 把c2的元素的添加到c集合 中去。 c2.clear(); //clear()清空集合中的元素 System.out.println("删除成功吗?"+c.remove("美美")); // remove 指定集合中的元素删除,删除成功返回true 否则false c.removeAll(c2); //删除c集合中与c2的交集元素。 c.retainAll(c2); //保留c集合与c2的交集元素, //其他的元素一并删除。 */ System.out.println("查看元素个数:"+c.size()); System.out.println("集合的元素:"+ c); /* 判断 isEmpty() contains(Object o) containsAll(Collection<?> c) 其实contains方法内部是依赖于equals方法进行比较的。 contains是根据 传入的对象的equals进行比较的 */ 迭代: toArray() /*Collection c = new ArrayList(); c.add("令计划"); c.add("徐才厚"); c.add("周永康"); Object[] arr = c.toArray(); //把集合中的元素全部 存储到一个Object的数组中返回。 System.out.println("数组的元素:"+Arrays.toString(arr));*/ 返回的是Object类型的数组 如果要转换成指定的类型 就很麻烦 Object[] arr = list.toArray(); for (int i = 0;i < arr.length; i++) { String e = (String) arr[i]; System.out.println(e); } 那么就是用第二种方法: String[] array =new String[list.size()]; list.toArray(array); 数组的定义不能用基本类型,必须要用包装类型,如int就报错。 int[] i = new int[set.size()]; //报错 Integer[] i =new Integer[set.size()]; //正确 读取里面的元素有两种方法: Integer[] arr=new Integer[al.size]; for (int i =0; i < al.size(); i++) arr[i] = al.get(i); for (Integer x : arr)//内部是迭代器来实现的 System.out.print(x + " "); 总结: 1. 上面中是根接口Collection的基本方法 当然也是适用于List等实现接口中 2. 上面中的根接口存放的是Object类型 也可以指定数据类型采用泛型 如:Collection<String> collection=new ArrayList<String>(); 集合中泛型类型不可以用基本类型 而是要用包装类 (往期文章中有介绍包装类的可以看看) 集合中toArray以正确的顺序返回一个包含此列表中所有元素的数组 Object类型 不带参数的toArray方法: 数组不能强制转换 不带参数的toArray方法。来看一下这种情况 ArrayList<Integer> arrayList2=new ArrayList<Integer>(); arrayList2.add(1); Object[] qw=(Integer[])arrayList2.toArray(); 会报错 因为toArray()返回的是Object类型数组 记住是进行数据拷贝 数组然后再返回 注意:这个数组是纯Object 而不是由其他类型转换过来的Object类型 再看看这个栗子: String[] xx=new String[2]; xx[0]="1"; xx[1]="2"; Object[] aa=xx; String[] zz=(String[])aa; 这个栗子是可以的 因为aa是由String[]类型转换过来的 当然可以再强转回去 还有注意的是:(String[])aa; 中只能String[]不能(String)aa; 因为aa是数组类型 带参数的toArray方法 带参数的toArray方法,是根据参数数组的类型,构造了一个对应类型的,长度跟ArrayList的size一致的空数组,虽然方法本身还是以 Object数组的形式返回结果,不过由于构造数组使用的ComponentType跟需要转型的ComponentType一致,就不会产生转型异常。 栗子: Collection<String> collection=new ArrayList<String>(); collection.add("sdf"); collection.add("qwe"); collection.add("111"); collection.add("222"); String[] aStrings=new String[1]; aStrings=collection.toArray(aStrings); 如果astring数组小了就会返回一个新的对应泛型数组 赋值给aStrings 如果刚好或者大了就会把值传入参数中的astrings 多余的部分为null 而不是返回一个新的数组 注意:toArray(泛型)主要依靠的是arraycopy 但是它是native的 arraycopy是本地方法 native无法直接用java代码访问 Arraylist用get访问快 但是线程非安全 ArrayList:线程不安全,速度快 数组形式 Vector: 线程安全的,速度慢 数组形式(不多做介绍了 基本被淘汰了) LinkedList 链表形式 插入删除快(没用过) 迭代器是集合里面很重要的一部分 先来介绍一下迭代器吧 Iterator是一个迭代器接口,专门用来迭代各种Collection集合,包括Set集合和List集合。 Iterator接口包含以下三个方法: 1.boolean hasNext():如果被迭代的集合元素还没有被遍历,则返回true。 2.Object next():返回集合里下一个元素 3.void remove():移除集合里上一次next()返回的元素 栗子: Collection xCollection=new ArrayList(); xCollection.add("aa"); xCollection.add("bb"); xCollection.add("cc"); Iterator iterator=xCollection.iterator(); iterator.next(); iterator.remove(); while(iterator.hasNext()) { iterator.next(); iterator.remove(); } System.out.println(xCollection); listIterator() ListIterator继承了 Iterator 添加: hasPrevious() 判断是否存在上一个元素。 previous() 当前指针先向上移动一个单位,然后再取出当前指针指向的元素。 next(); 先取出当前指针指向的元素,然后指针向下移动一个单位。 add(E e) 把当前有元素插入到当前指针指向的位置上。 每次add的时候add方法内部已经指针向后移动一位了 set(E e) 替换迭代器最后一次返回的元素。 比较: Java的Iterator只能够单向移动,从而这个Iterator只能够用来做以下的事情: 1)使用iterator()方法要求容器返回一个Iterator。Iterator将准备好返回序列的第一个元素。 2)使用next()获取序列的下一个元素。 3)使用hasNext()来检测序列中是否还有元素。 4)使用remove()将迭代器新近返回的元素删除。 ——————ListItarator————— ListIterator是一个更加强大的Iterator的子类型,它只能用于List类的访问。 尽管Iterator只能够向前移动,但是ListItarator可以双向移动。 可用的方法: 1)使用hasNext()来检测序列中是否还有元素。 2)使用next()获取序列的下一个元素。 3)使用hasPrevious()来检测序列中是否有上一个元素。 4)使用previous()获取序列的上一个元素。 5)set()方法替换它访问过的最后一个元素。 6)listIterator()方法产生一个指向List开始处的ListIterator。 7)listIterator(n)方法产生一个指向列表索引为n的元素处的ListIterator。 直接看大佬总结的吧 很完善 https://blog.csdn.net/longshengguoji/article/details/41551491 https://blog.csdn.net/StubbornAccepted/article/details/54562154 总结: 使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型。 重点: 迭代器在变量元素的时候要注意事项: 在迭代器迭代元素 的过程中,不允许使用集合对象改变集合中的元素 个数,如果需要添加或者删除只能使用迭代器的方法进行操作。 如果使用过了集合对象改变集合中元素个数那么就会出现ConcurrentModificationException异常。 迭代元素 的过程中: 迭代器创建到使用结束的时间。 意思就是说迭代器创建到迭代器的使用中间不能出现集合控制集合个数的操作 要操作只能用迭代器方法 操作的结果会显示在集合中 add会跳过添加的下一位 注意: NoSuchElementException 没有元素的异常。 出现的原因: 没有元素可以被迭代了。。。 集合三大体系之List: 背景: 有序: 集合的有序不是指自然顺序,而是指添加进去的顺序与元素出来的顺序是一致的。 只有List接口下面的集合类才具备索引值。其他接口下面的集合类都没有索引值。 但是集合不能直接集合[i]进行调用 List接口中特有方法: 添加 add(E element)添加到末尾 addAll(Collection<? extends E> c)添加到末尾 add(int index, E element) 把元素添加到集合中的指定索引值位置上。 addAll(int index, Collection<? extends E> c) 把list2的元素添加到list集合指定索引值的位置上。 获取: get(int index) 根据索引值获取集合中的元素 indexOf(Object o) 元素第一次出现在集合中 的索引值 lastIndexOf(Object o) 指定的元素最后一次出现在集合中的索引值 subList(int fromIndex, int toIndex) 指定开始与结束的索引值截取集合中的元素。 修改: set(int index, E element) 使用指定的元素替换指定索引值位置的元素。 迭代 listIterator() List接口特有的迭代器 注意: 可以直接输出list集合 数据出来顺序和add加入的顺序是一样的 get只有list以及子类可以使用 for (int i = 0; i < list.size() ; i++) { System.out.print(list.get(i)+","); } 截取子集 List subList = list.subList(1, 3); //指定开始与结束的索引值截取集合中的元素。 System.out.println("子集合的元素是:"+ subList); ArrayList: ArrayList 特有的方法: ensureCapacity(int minCapaci上ty) 指定初始容量 但是一般都是构造函数的时候初始容量 trimToSize() 删除不用的内容 比如十个里面只用到了3个 删除后面7个 但不常用 笔试题目: 使用ArrayList无参的构造函数创建一个 对象时, 默认的容量是多少? 如果长度不够使用时又自增增长多少? ArrayList底层是维护了一个Object数组实现 的,使用无参构造函数时,Object数组默认的容量是10,当长度不够时,自动增长0.5倍。 使用三种方式遍历集合的元素. List xx=new ArrayList(); xx.add("aa"); xx.add("bb"); xx.add("cc"); xx.add(1,"dd"); //第一种get for(int i=0;i<4;i++) { System.out.print(xx.get(i)+" "); } System.out.print("\n"); //第二种迭代器 ListIterator listIterator=xx.listIterator(); while(listIterator.hasNext()) { System.out.print(listIterator.next()+" "); } System.out.print("\n"); // System.out.print(listIterator.next()+" "); //报错 因为超出范围了 //第三种逆序迭代 while(listIterator.hasPrevious()) { System.out.print(listIterator.previous()+" "); } System.out.print("\n"); // for(Object zz: xx) { System.out.print(zz+" "); } // 需求: 编写一个函数清除集合中重复元素。 如果书号是一样就视为重复元素。 要求: 遍历集合元素的时候必须使用迭代器。 get 迭代器 public static ArrayList clearRepeat(ArrayList list){ //创建一个新的集合 ArrayList newList = new ArrayList(); //获取迭代器 Iterator it = list.iterator(); while(it.hasNext()){ Book book = (Book) it.next(); //从旧集合中获取的元素 if(!newList.contains(book)){ //如果新集合没有包含该书籍,那么就存储到新集合中 newList.add(book); } } return newList; } Linkedlist: Linkedlist特有的方法: 1:方法介绍 addFirst(E e) addLast(E e) getFirst() getLast() removeFirst() removeLast() 2:数据结构 1:栈 (1.6) : 主要是用于实现堆栈数据结构的存储方式。 先进后出 push() 左边压入 pop() 左边取出 2:队列(双端队列1.5): 主要是为了让你们可以使用LinkedList模拟队列数据结构的存储方式。 先进先出 offer() 右边压入 poll() 左边取出 3:返回逆序的迭代器对象 descendingIterator() 返回逆序的迭代器对象 Iterator it = list.descendingIterator(); while(it.hasNext()){ System.out.println(it.next()); } 返回的是逆序的 List总结: 集合 的体系: ------------| Collection 单例集合的根接口 ----------------| List 如果是实现了List接口的集合类,具备的特点: 有序,可重复。 -------------------| ArrayList ArrayList 底层是维护了一个Object数组实现的。 特点: 查询速度快,增删慢。 -------------------| LinkedList LinkedList 底层是使用了链表数据结构实现的, 特点: 查询速度慢,增删快。 -------------------| Vector(了解即可) 底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低。 ----------------| Set 如果是实现了Set接口的集合类,具备的特点: 无序,不可重复。 笔试题: 说出ArrayLsit与Vector的区别? 相同点: ArrayList与Vector底层都是使用了Object数组实现的。 不同点: 1. ArrayList是线程不同步的,操作效率高。 Vector是线程同步的,操作效率低。 2. ArrayList是JDK1.2出现,Vector是jdk1.0的时候出现的。 */ public class Demo1 { public static void main(String[] args) { Vector v = new Vector(); //添加元素 v.addElement("张三"); v.addElement("李四"); v.addElement("王五"); //迭代该集合 Enumeration e = v.elements(); //获取迭代器 while(e.hasMoreElements()){ System.out.println(e.nextElement()); } } } 集合三大体系之Set: set之HashSet ——–| Set 如果是实现了Set接口的集合类,具备的特点: 无序,不可重复。 ————-| HashSet 底层是使用了哈希表来支持的,特点: 存取速度快. hashSet的实现原理: 往Haset添加元素的时候,HashSet会先调用元素的hashCode方法得到元素的哈希值 , 然后通过元素 的哈希值经过移位等运算,就可以算出该元素在哈希表中 的存储位置。 情况1: 如果算出元素存储的位置目前没有任何元素存储,那么该元素可以直接存储到该位置上。 情况2: 如果算出该元素的存储位置目前已经存在有其他的元素了,那么会调用该元素的equals方法与 该位置的元素再比较一次,如果equals返回的是true,那么该元素与这个位置上的元素就视为重复元素 ,不允许添加,如果equals方法返回的是false,那么该元素运行 添加。 @Override public int hashCode() { System.out.println("=======hashCode====="); return this.id; } @Override public boolean equals(Object obj) { System.out.println("======equals======"); Person p = (Person)obj; return this.id==p.id; } 重写hascode和equals HashSet set = new HashSet(); set.add(new Person(110,"狗娃")); set.add(new Person(220,"狗剩")); set.add(new Person(330,"铁蛋")); //在现实生活中只要编号一致就为同一个人. System.out.println("添加成功吗?"+set.add(new Person(110,"狗娃"))); System.out.println("集合的元素:"+set); 1.equal()相等的两个对象他们的hashCode()肯定相等,也就是用equal()对比是绝对可靠的。 2.hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。 所有对于需要大量并且快速的对比的话如果都用equal()去做显然效率太低,所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性! 这种大量的并且快速的对象对比一般使用的hash容器中,比如hashset,hashmap,hashtable等等,比如hashset里要求对象不能重复,则他内部必然要对添加进去的每个对象进行对比,而他的对比规则就是像上面说的那样,先hashCode(),如果hashCode()相同,再用equal()验证,如果hashCode()都不同,则肯定不同,这样对比的效率就很高了。 总结: 1、equals方法用于比较对象的内容是否相等(覆盖以后) 2、hashcode方法只有在集合中用到 3、当覆盖了equals方法时,比较对象是否相等将通过覆盖后的equals方法进行比较(判断对象的内容是否相等)。 4、将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。 。HashSet,就是通过其中的元素(对象)的hashconde来区分对象是否唯一的。所以,HashSet的对象中着一个集合中对象的hashcode的list,每次执行set.add(obj)的时候,都会取出obj的hashcode与其内部的list进行比较,如果没有与之相等的,就加进set里去,同时把那个obj的hashcode加到list里面去;如果有相等的,就再调用obj的equals方法与各个对象进行比较,如果没有相等的,就加入到set里面去,如果还有相等的,就不执行加入操作。 **总结HashSet : 哈希表是根据hasCode来存放的 如果hasCode一样的话 equals又不一样 那么两个对象都是放在同一个hasCode地址内的 而且interator的输出顺序是无序的** set之TreeSet TreeSet() /* treeSet添加自定义元素: treeSet要注意的事项: 1. 往TreeSet添加元素的时候,如果元素本身具备了自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。 2. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,那么该元素所属的类必须要实现Comparable接口,把元素 的比较规则定义在compareTo(T o)方法上。 3. 如果比较元素的时候,compareTo方法返回 的是0,那么该元素就被视为重复元素,不允许添加. (注意:TreeSet与HashCode、equals方法是没有任何关系。) 4. 往TreeSet添加元素的时候, 如果元素本身没有具备自然顺序 的特性, 而元素所属的类也没有实现Comparable接口,那么必须要在创建TreeSet的时候传入一个 比较器。 5. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,而元素所属的类已经实现了 Comparable接口, 在创建TreeSet对象的时候也传入了比较器那么是以比较器的比较规则优先使用。 如何自定义定义比较器: 自定义一个类实现Comparator接口即可,把元素与元素之间的比较规则定义在compare方法内即可。 自定义比较器的格式 : class 类名 implements Comparator{ } 推荐使用:使用比较器(Comparator)。 栗子: public int compareTo(Object arg0) { Person person=(Person)arg0; return this.number-person.number; } 就是比较number来排序对象 如果0则重复不添加 如果this.number-person.number则为从小到大排序 person.number-this.number则相反 举例: class Person implements Comparable{ int temp; int number; public Person(int temp,int number){ this.temp=temp; this.number=number; } @Override public String toString() { // TODO Auto-generated method stub return this.temp+" "+this.number; } @Override public int compareTo(Object arg0) { // TODO Auto-generated method stub Person person=(Person)arg0; return this.number-person.number; } } class MyComparator implements Comparator{ @Override public int compare(Object arg0, Object arg1) { Person person1=(Person)arg0; Person person2=(Person)arg1; return person1.temp-person2.temp; 从小到大 } } class new1{ public static void main(String[] args) { MyComparator myComparator=new MyComparator(); Set set=new TreeSet(myComparator); set.add(new Person(1,4)); set.add(new Person(2,3)); set.add(new Person(6,2)); set.add(new Person(4,1)); set.add(new Person(3,0)); System.out.println(set); } public static void ha(Object zz) { } } 总结 如果没有自然顺序就需要自定义添加类继承Comparable接口并且改写compareTo方法 或者定义类继承Comparator接口 然后传入TreeSet 如果两个都有那么就按照Comparetor的来排序 TreeSet是可以对字符串进行排序 的, 因为字符串已经实现了Comparable接口。 字符串的比较规则: 情况一: 对应位置有不同的字符出现, 就比较的就是对应位置不同的字符。 情况 二:对应位置上 的字符都一样,比较的就是字符串的长度。 /* 需求:将字符串中的数值进行排序。 例如String str=”8 10 15 5 2 7”; —-> “2 5 7 8 10 15” */ public class Demo8 { public static void main(String[] args) { String str="8 10 15 5 2 7"; String[] datas = str.split(" "); TreeSet tree = new TreeSet(); for(int i = 0 ; i<datas.length ; i++){ tree.add(Integer.parseInt( datas[i])); // 字符串转int类型数据是需要使用Integer.parseInt() } //遍历treeSet的元素拼接成对应的字符串 Iterator it = tree.iterator(); while(it.hasNext()){ System.out.print(it.next()+" "); } } } 实现 如果号码相同就按照名字来排序 public int compareTo(Object arg0) { // TODO Auto-generated method stub Person person=(Person)arg0; if((this.number-person.number)!=0) return this.number-person.number; else { return this.name.compareTo(person.name); } } 集合三大体系之Map: Map与List、Set接口不同,它是由一系列键值对组成的集合,提供了key到Value的映射。同时它也没有继承Collection。在Map中它保证了key与value之间的一一对应关系。也就是说一个key对应一个value,所以它不能存在相同的key值,当然value值可以相同。实现map的有:HashMap、TreeMap、HashTable、Properties、EnumMap。 HashMap: 创建对象: > Map<String, Integer> map=new HashMap<String,Integer>(); 添加:put 可以相同的key值,但是添加的value值会覆 盖前面的,返回值是前一个,如果没有就返回null 添加一个对象:putAll:如果重复了 添加的那个会覆盖掉前面的 返回值方法 删除内容 remove 传入键 删除该键对应的对象( 删除关联对象,指定key对象) 全部删除 clear(); 判断是否为空: isEmpty(); 断集合中是否包含指定的key boolean containsKey(Object key) 判断集合中是否包含指定的value boolean containsValue(Object value) 返回map的长度 size() get(Object key) 通过指定的key对象获取value对象 如果没有的话 就返回null 遍历Map 迭代的方法迭代: keySet() values() entrySet() 1.map转换成set类型 通过map.keySet 然后遍历Iterator遍历set返回key值通过map的get来得到值 Set<String> set=map.keySet(); Iterator<String> iterator=set.iterator(); while(iterator.hasNext()) { String num=iterator.next(); System.out.println(map.get(num)); 2.// 第二种方式: // 通过values 获取所有值,不能获取到key对象 // Collection<V> values() Collection<String> vs = map.values(); Iterator<String> it = vs.iterator(); while (it.hasNext()) { String value = it.next(); System.out.println(" value=" + value); 3.将map对象传入set 第三种方式: Map.Entry public static interface Map.Entry<K,V> 通过Map中的entrySet()方法获取存放Map.Entry<K,V>对象的Set集合。 Set<Map.Entry<K,V>> entrySet() 面向对象的思想将map集合中的键和值映射关系打包为一个对象,就是Map.Entry ,将该对象存入Set集合,Map.Entry是一个对象,那么该对象具备的getKey,getValue获得键和值。 Set<Map.Entry<String, Integer>> set=map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator=set.iterator(); while(iterator.hasNext()) { //返回的是封装了key和value对象的Map.Entry对象 Map.Entry<String, Integer> it=iterator.next(); String aString=it.getKey(); int a=it.getValue(); System.out.println(aString+a); 举栗子: 底层是哈希表数据结构,线程是不同步的,可以存入null键,null值。要保证键的唯一性,需要覆盖hashCode方法,和equals方法。 案例:自定义对象作为Map的键。 class Person{ public String name; public int age; public Person(String name,int age) { this.name=name; this.age=age; } @Override public boolean equals(Object arg0) { // TODO Auto-generated method stub if(arg0 instanceof Person) { Person person=(Person)arg0; return this.name.equals(person.name)&&this.age==person.age; }else { return false; } } @Override public int hashCode() { // TODO Auto-generated method stub return this.name.hashCode()+age*20; } @Override public String toString() { // TODO Auto-generated method stub return this.name+" "+this.age; } } class new1{ public static void main(String[] args) { Map<Person, Integer> map=new HashMap<Person,Integer>(); map.put(new Person("a", 1), 2); map.put(new Person("b", 1), 2); map.put(new Person("b", 1), 2); map.put(new Person("c", 1), 3); map.put(new Person("d", 1), 4); Set<Map.Entry<Person, Integer>> set=map.entrySet(); Iterator<Map.Entry<Person, Integer>> iterator=set.iterator(); while(iterator.hasNext()) { Map.Entry<Person, Integer> aEntry=iterator.next(); Person xPerson=aEntry.getKey(); int a=aEntry.getValue(); System.out.println(xPerson+"|"+a); } System.out.println(map); } } TreeMap 内部以red-black(红-黑)树数据结构实现 TreeMap的排序,TreeMap可以对集合中的键进行排序。如何实现键的排序? 方式一:元素自身具备比较性 和TreeSet一样原理,需要让存储在键位置的对象实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。 方式二:容器具备比较性 当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。 注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主; 注意:在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较次要条件。(假设姓名和年龄一直的人为相同的人,如果想要对人按照年龄的大小来排序,如果年龄相同的人,需要如何处理?不能直接return 0,以为可能姓名不同(年龄相同姓名不同的人是不同的人)。此时就需要进行次要条件判断(需要判断姓名),只有姓名和年龄同时相等的才可以返回0.) 通过return 0来判断唯一性。 举例: class Person implements Comparable<Person> { public String name; public int age; public Person(String name,int age) { this.name=name; this.age=age; } @Override public int compareTo(Person arg0) { // TODO Auto-generated method stub if((this.age-arg0.age)==0) { return this.age-arg0.age; }else { return this.name.compareTo(arg0.name); } } @Override public String toString() { // TODO Auto-generated method stub return this.name+" "+this.age; } } class MyComparator implements Comparator<Person>{ @Override public int compare(Person arg0, Person arg1) { // TODO Auto-generated method stub return arg1.age-arg0.age; } } class new1{ public static void main(String[] args) { MyComparator xx=new MyComparator(); Map<Person, Integer> map=new TreeMap<Person, Integer>(); map.put(new Person("a", 1), 2); map.put(new Person("b", 2), 2); map.put(new Person("c", 3), 3); map.put(new Person("d", 4), 4); Set<Map.Entry<Person, Integer>> set=map.entrySet(); Iterator<Map.Entry<Person, Integer>> iterator=set.iterator(); while(iterator.hasNext()) { Map.Entry<Person, Integer> aEntry=iterator.next(); Person xPerson=aEntry.getKey(); int a=aEntry.getValue(); System.out.println(xPerson+"|"+a); } System.out.println(map); } } 集合的练习 问题: 定义一个Person数组,将Person数组中的重复对象剔除? 思路: 1. 描述一个Person类 2. 将数组转换为Arrays.asList() List 3. Set addAll( list ) 4. hashCode()且equals() import java.util.Arrays; import java.util.Set; import java.util.List; import java.util.HashSet; // 1. 描述Person类 class Person { public String name; public int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String toString() { return getClass().getName() + " : name=" + this.name + " age=" + this.age; } // 4. 重写hashCode和equals() public int hashCode() { return this.age; } public boolean equals(Object o) { Person p = null; if (o instanceof Person) p = (Person) o; return this.name.equals(p.name) && (this.age == p.age); } } class Demo2 { public static void main(String[] args) { Person[] ps = new Person[] { new Person("jack", 34), new Person("lucy", 20), new Person("lili", 10), new Person("jack", 34) }; // 遍历数组 System.out.println(Arrays.toString(ps)); // 2. 将自定义对象数组转换为List集合 List<Person> list = Arrays.asList(ps); // 3. 将List转换为Set Set<Person> set = new HashSet<Person>(); set.addAll(list); System.out.println(set); } } 关于数组操作 4.Collections与Arrays 集合框架中的工具类:特点:该工具类中的方法都是静态的。 Collections:常见方法: 1,对list进行二分查找: 前提该集合一定要有序。 int binarySearch(list,key); 求元素所在的索引 (有自然顺序)常用 //必须根据元素自然顺序对列表进行升级排序 //要求list 集合中的元素都是Comparable 的子类。 int binarySearch(list,key,Comparator); 如果是自定义类求键的索引 要传入比较器 key是键 2,对list集合进行排序。 sort(list); //对list进行排序,其实使用的事list容器中的对象的compareTo方法 sort(list,comaprator); 常用 //按照指定比较器进行排序 3,对集合取最大值或者最小值。 常用 max(Collection) max(Collection,comparator) 不具备自然顺序的 min(Collection) min(Collection,comparator) 4,对list集合进行反转。 reverse(list); 不需要传入比较器 因为没有比较过程 5,对比较方式进行强行逆转。 Comparator reverseOrder(); Comparator reverseOrder(Comparator); 6,对list集合中的元素进行位置的置换。 swap(list,x,y); 7,对list集合进行元素的替换。如果被替换的元素不存在,那么原集合不变。 replaceAll(list,old,new); 8,可以将不同步的集合变成同步的集合。 在方法中加synchronized同步锁来实现的。我们知道synchronized锁的开销较大,在程序中不建议使用。 Set synchronizedSet(Set<T> s) Map synchronizedMap(Map<K,V> m) List synchronizedList(List<T> list) 9. 如果想要将集合变数组: 可以使用Collection 中的toArray 方法。注意:是Collection不是Collections工具类 传入指定的类型数组即可,该数组的长度最好为集合的size。 Arrays:用于对数组操作的工具类 1,二分查找,数组需要有序 binarySearch(int[]) binarySearch(double[]) 2,数组排序 sort(int[]) sort(char[])…… 2,将数组变成字符串。 toString(int[]) 3,复制数组。 copyOf(arr,newLenght); newlenght是新数组的长度 如果arr是int new大了的话 剩余是0 如果arr是Integer new大了的话 剩余是null 4,复制部分数组。 copyOfRange(arr,int from,int to):包头不包尾 5,比较两个数组是否相同。 对应位置的元素是否一致 equals(int[],int[]) Arrays.equals改写了object的equals 6,将数组变成集合。 集合可以通过toarray变数组 数组也可以变集合 List asList(T[]); List<Integer> aIntegers=Arrays.asList(a); 这样可以通过集合的操作来操作数组中元素, 但是不可以使用增删方法,add,remove。因为数组长度是固定的,会出现 UnsupportOperationExcetion。 可以使用的方法:contains,indexOf。。。 如果数组中存入的基本数据类型,那么asList会将数组实体作为集合中的元素。 如果数组中的存入的引用数据类型,那么asList会将组中的元素作为集合中 的元素。 import java.util.ArrayList; import java.util.Collections; import java.util.Arrays; import java.util.List; class Demo1 { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<Integer>(); list.add(4); list.add(3); list.add(1); list.add(2); list.add(3); // 排序 Collections.sort(list); // 折半查找的前提是排序好的元素 System.out.println( Collections.binarySearch( list , 8 ) ); // 找不到返回-插入点-1 // 反序集合输出 Collections.reverse( list ); System.out.println( list ); // 求最值 System.out.println( Collections.max( list ) ); // 4 // fill() 使用指定的元素替换指定集合中的所有元素 // Collections.fill( list, 5 ); System.out.println( list ); // 将数组转换为集合 Integer is[] = new Integer[]{6,7,8}; List<Integer> list2 = Arrays.asList(is); list.addAll( list2 ); System.out.println( list ); // 将List转换为数组 Object [] ins = list.toArray(); System.out.println( Arrays.toString( ins ) ); } } 总结: list还有map都可以使用get set不行 因为set没有索引 是无序的 先插入的数不一定先输出 比较的话 Hash表需要改写hashCode和equals return 0表示重复 Tree的话需要继承Comparable重写或者定义比较容器 继承Comparator this-传入的值 就是从小到大排序 返回0就是重复添加 比较字符串是否相等用equals 比较字符串大小用compareTo Map和Set类似方法 Map 键不能重复 HashMap底层是哈希表数据结构,线程是不同步的,可以存入null键,null值。 HashMap有一个叫做Entry的内部类,它用来存储key-value对。 要保证键的唯一性,需要覆盖hashCode方法,和equals方法。 | LinkedHashMap: 该子类基于哈希表又融入了链表。可以Map集合进行增删提高效率。 TreeMap 底层是二叉树数据结构。可以对map集合中的键进行排序。需要使用Comparable或者Comparator 进行比较排序。return 0,来判断键的唯一性。 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大。但数组的二分查找时间复杂度小,为O(1);数组的特点是:寻址容易,插入和删除困难; 链表 链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。链表的特点是:寻址困难,插入和删除容易。 哈希表 那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表。哈希表((Hash table)既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便。 Java集合细节–一: 用数组转list用Arrays.asList 1. 但是这个数组不能用基本类型 而是要用包装类 2. 不要试图改变asList返回的列表,长度不可变 参考: http://cmsblogs.com/?p=106 http://cmsblogs.com/?cat=5 为集合指定初始容量: http://cmsblogs.com/?p=1226

优秀的个人博客,低调大师

java学习笔记--数组操作(Collections和Arrays)

关于数组操作 4.Collections与Arrays 集合框架中的工具类:特点:该工具类中的方法都是静态的。 Collections:常见方法: 1,对list进行二分查找: 前提该集合一定要有序。 int binarySearch(list,key); 求元素所在的索引 (有自然顺序)常用 //必须根据元素自然顺序对列表进行升级排序 //要求list 集合中的元素都是Comparable 的子类。 int binarySearch(list,key,Comparator); 如果是自定义类求键的索引 要传入比较器 key是键 2,对list集合进行排序。 sort(list); //对list进行排序,其实使用的事list容器中的对象的compareTo方法 sort(list,comaprator); 常用 //按照指定比较器进行排序 3,对集合取最大值或者最小值。 常用 max(Collection) max(Collection,comparator) 不具备自然顺序的 min(Collection) min(Collection,comparator) 4,对list集合进行反转。 reverse(list); 不需要传入比较器 因为没有比较过程 5,对比较方式进行强行逆转。 Comparator reverseOrder(); Comparator reverseOrder(Comparator); 6,对list集合中的元素进行位置的置换。 swap(list,x,y); 7,对list集合进行元素的替换。如果被替换的元素不存在,那么原集合不变。 replaceAll(list,old,new); 8,可以将不同步的集合变成同步的集合。 在方法中加synchronized同步锁来实现的。我们知道synchronized锁的开销较大,在程序中不建议使用。 Set synchronizedSet(Set s) Map synchronizedMap(Map import java.util.ArrayList; import java.util.Collections; import java.util.Arrays; import java.util.List; class Demo1 { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<Integer>(); list.add(4); list.add(3); list.add(1); list.add(2); list.add(3); // 排序 Collections.sort(list); // 折半查找的前提是排序好的元素 System.out.println( Collections.binarySearch( list , 8 ) ); // 找不到返回-插入点-1 // 反序集合输出 Collections.reverse( list ); System.out.println( list ); // 求最值 System.out.println( Collections.max( list ) ); // 4 // fill() 使用指定的元素替换指定集合中的所有元素 // Collections.fill( list, 5 ); System.out.println( list ); // 将数组转换为集合 Integer is[] = new Integer[]{6,7,8}; List<Integer> list2 = Arrays.asList(is); list.addAll( list2 ); System.out.println( list ); // 将List转换为数组 Object [] ins = list.toArray(); System.out.println( Arrays.toString( ins ) ); } }

优秀的个人博客,低调大师

java学习笔记--枚举类(综合网络用法)

什么是枚举类? 个人理解就是一个 定义了一个规范 你只能从固定的一些值中取值,限定了范围 比如性别,四季就可以用枚举类 而且是类型安全的 意思就是 你不能传入int之类的其他变量给枚举类 枚举类可以定义在一个类里 也可以单独定义 使用enum关键字 枚举类的定义格式: enum 类名{ //枚举值 } 枚举要注意的细节: 1. 枚举类也是一个特殊的类。 2. 枚举值默认的修饰符是public static final。 3. 枚举值就是是枚举值所属的类的类型, 然后枚举值是指向了本类的对象的。 4. 枚举类的构造方法默认的修饰符是private的。 5. 枚举类可以定义自己的成员变量与成员函数。 6. 枚举类可以自定义构造函数,但是构造函数的修饰符必须是private。 7. 枚举类可以存在抽象 的方法,但是枚举值必须要实现抽象 的方法。 8. 枚举值必须要位于枚举类 的第一个语句。 总的来说 枚举值就是枚举类的实例 可以单独一个枚举值 也可以枚举值绑定一个变量 下面会介绍的 枚举用法一: 常量值 enum Sex{ 男, 女 }//男 女是Sex的实例 分隔符用逗号 如何遍历枚举? for(Sex s : Sex.values()){ System.out.println(Sex.name); //name是枚举值的名字 如上那就是男和女 } 枚举用法二: switch //季节枚举类 enum Season{ spring,summer,autumn,winter; } public eclass Demo8 { public static void main(String[] args) { Season season = Season.summer; switch(season){ case spring: System.out.println("春天..."); break; case summer: System.out.println("夏天..."); break; case autumn: System.out.println("秋天..."); break; case winter: System.out.println("冬天..."); break; } } }//switch里面直接放枚举值 不要加枚举类名字 ———————————————————————————————————————————————————————————————————————————— 枚举用法三:枚举类有方法 枚举值和参数绑定 构造函数是private的 enum Gender{ // public static final Sex man = new Sex("man"); 要重写Gender才行 用来覆盖无参的构造函数 man("男"),woman("女"); String value; //成员 变量 private Gender(String value){ this.value = value; } } ———————————————————————————————————————————————————————————————————————— //**枚举用法四:覆盖枚举的方法** enum Sex{ // public static final Sex man = new Sex("man"); man("男"){//匿名类 @Override public void run() { System.out.println("男人在跑..."); } },woman("女"){ @Override public void run() { System.out.println("女人在跑..."); } }; //枚举值 String value; //成员 变量 public类型的 // public static final Sex man = new Sex(); //构造函数 private Sex(String value){ this.value = value; } //成员函数 public void getValue(){ System.out.println("value :"+ value); } public abstract void run(); } —————————————————————————————————————————————————————————————————————————————— 用法五:实现接口 public interface Behaviour { void print(); String getInfo(); } public enum Color implements Behaviour{ RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this.name = name; this.index = index; } //接口方法 @Override public String getInfo() { return this.name; } //接口方法 @Override public void print() { System.out.println(this.index+":"+this.name); } } —————————————————————————————————————————————————————————————————————————————————————— 用法六:使用接口组织枚举 public interface Food { enum Coffee implements Food{ BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO } enum Dessert implements Food{ FRUIT, CAKE, GELATO } } switch适用的数据类型: byte \ char \short \ int \ String\枚举类型 注意: switch中 case语句后面跟的枚举值,只需要单写枚举值即可,不需要再声明该 枚举值是属于哪个枚举类的。

优秀的个人博客,低调大师

java学习笔记--io流的异常处理

public static void main(String[] args) { // readTest(); copyImage(); } // 拷贝图片 public static void copyImage() { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { // 找到目标文件 File inFile = new File("F:\\美女\\1.jpg"); File outFile = new File("E:\\1.jpg"); // 建立输入输出通道 fileInputStream = new FileInputStream(inFile); fileOutputStream = new FileOutputStream(outFile); // 建立缓冲数组,边读边写 byte[] buf = new byte[1024]; int length = 0; while ((length = fileInputStream.read(buf)) != -1) { fileOutputStream.write(buf, 0, length); } } catch (IOException e) { System.out.println("拷贝图片出错..."); throw new RuntimeException(e);//读取的错误 } finally { // 关闭资源 try { if (fileOutputStream != null) { fileOutputStream.close(); System.out.println("关闭输出流对象成功..."); } } catch (IOException e) {//关闭的错误 System.out.println("关闭输出流资源失败..."); throw new RuntimeException(e); } finally { if (fileInputStream != null) { try { fileInputStream.close(); System.out.println("关闭输入流对象成功..."); } catch (IOException e) { System.out.println("关闭输入流对象失败..."); throw new RuntimeException(e); } } } } } 总结:io流抛出异常的位置有两个 1. 打开的文件的时候 文件损坏或者硬盘损坏等 主要是 抛出包装后的错误信息RuntimeException(e) 2. 流关闭放在finally中 但是关闭流的时候也会发生错误 3. 如果io流抛出异常 就无法执行接下里的任务 所以我们要try{} catch(){}finally{}

优秀的个人博客,低调大师

SpringCloud学习之sleuth&zipkin【二】

这篇文章我们解决上篇链路跟踪的遗留问题 一、将追踪数据存放到MySQL数据库中 默认情况下zipkin将收集到的数据存放在内存中(In-Memeroy),但是不可避免带来了几个问题: 在服务重新启动后,历史数据丢失。 在数据量过大的时候容易造成OOM错误 通常做法是与mysql或者ElasticSearch结合使用,那么我们先把收集到的数据先存到Mysql数据库中 1、改造zipkin-server的依赖 gradle配置: dependencies { compile('org.springframework.cloud:spring-cloud-starter-eureka') compile('org.springframework.cloud:spring-cloud-starter-config') // compile('io.zipkin.java:zipkin-server') compile 'org.springframework.cloud:spring-cloud-starter-sleuth' compile('io.zipkin.java:zipkin-autoconfigure-ui') runtime('mysql:mysql-connector-java') compile('org.springframework.boot:spring-boot-starter-jdbc') compile('org.springframework.cloud:spring-cloud-sleuth-zipkin-stream') compile('org.springframework.cloud:spring-cloud-stream') compile('org.springframework.cloud:spring-cloud-stream-binder-kafka') } View Code 这里将原先的io.zipkin.java:zipkin-server 替换为 spring-cloud-sleuth-zipkin-stream 该依赖项包含了对mysql存储的支持,同时添加spring-boot-starter-jdbc与mysql的依赖,顺便把kafka的支持也加进来 注意:此处脚本最好在数据库中执行一下,当然我们也可以在下面的配置文件中做初始化的相关配置 2、YAML中的关键配置项: spring: datasource: username: root password: root url: jdbc:mysql://localhost:3306/myschool?characterEncoding=utf-8&useSSL=false initialize: true continue-on-error: true kafka: bootstrap-servers: localhost:9092 server: port: 9000 zipkin: storage: type: mysql View Code 注意zipkin.storage.type 指定为mysql 3、更改启动类 package com.hzgj.lyrk.zipkin.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.sleuth.zipkin.stream.EnableZipkinStreamServer; @EnableZipkinStreamServer @SpringBootApplication public class ZipkinServerApplication { public static void main(String[] args) { SpringApplication.run(ZipkinServerApplication.class, args); } } View Code 这里注意将@EnableZipkinServer改成@EnableZipkinStreamServer 二、将收集信息改成异步发送 这步改造主要用以提高性能与稳定性,服务将收集到的span无脑的往消息中间件上丢就可以了,不用管zipkin的地址在哪里。 1、改造Order-Server依赖: gradle: compile('org.springframework.cloud:spring-cloud-starter-eureka-server') // compile('org.springframework.cloud:spring-cloud-sleuth-zipkin') compile 'org.springframework.cloud:spring-cloud-starter-sleuth' compile 'org.springframework.cloud:spring-cloud-sleuth-stream' compile('org.springframework.cloud:spring-cloud-starter-config') compile('org.springframework.cloud:spring-cloud-stream') compile('org.springframework.cloud:spring-cloud-stream-binder-kafka') compile('org.springframework.kafka:spring-kafka') compile('org.springframework.cloud:spring-cloud-starter-bus-kafka') View Code 这里把原先的spring-cloud-sleuth-zipkin改成spring-cloud-sleuth-stream,不用猜里面一定是基于spring-cloud-stream实现的 2、YAML关键属性配置: server: port: 8100 logging: level: org.springframework.cloud.sleuth: DEBUG spring: sleuth: sampler: percentage: 1.0 View Code 注意:这里设置低采样率会导致span的丢弃。我们同时设置sleuth的日志输出为debug 3、同理改造其他的微服务 三、验证结果 数据库里的相关数据:

优秀的个人博客,低调大师

Jenkins Linux下安装、配置(学习笔记一)

1、安装JDK、Jenkins yum install java-1.8.0-openjdk.x86_64 -y sudo wget -O /etc/yum.repos.d/jenkins.repohttp://pkg.jenkins-ci.org/redhat/jenkins.repo sudo rpm --importhttps://jenkins-ci.org/redhat/jenkins-ci.org.key sudo yum install jenkins -y sudo service jenkins start sudo chkconfig jenkins on 2、关闭防火墙 firewall-cmd --permanent --new-service=jenkins firewall-cmd --permanent --service=jenkins --set-short="Jenkins Service Ports" firewall-cmd --permanent --service=jenkins --set-description="Jenkins service firewalld port exceptions" firewall-cmd --permanent --service=jenkins --add-port=8080/tcp firewall-cmd --permanent --add-service=jenkins firewall-cmd --zone=public--add-service=http --permanent firewall-cmd --reload 3、浏览器输入http://ip:8080 4、获取密码:cat /var/lib/jenkins/secrets/initialAdminPassword xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 5、安装推荐的插件 6、创建用户

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册