首页 文章 精选 留言 我的

精选列表

搜索[整理],共9145篇文章
优秀的个人博客,低调大师

Java面试整理《上》

一、Java基础部分 简单介绍下Java的跨平台原理不同的操作系统的操作指令集不同,所以做程序开发的时候需要根据不同的操作系统开发程序。比如想要程序支持MacOS、Windows和Linux就要开发三套不同的程序代码。这会导致开发成本成倍提升,所以很多程序都只开发了windows版本。这是相对于桌面程序来说的,如果是WEB应用程序就没有这个烦恼,这也是WEB开发这么流行的原因。Sun公司开发了适用于不同操作系统及位数的JVM虚拟机来屏蔽系统之间的差异并提供了统一的接口,对于Java程序而言,只需要遵循Java语言规范,就可以在所有的操作系统上运行程序。 Java中int数据占用几个字节?int数据占用4个字节,这在哪个位数操作系统上都是一样的,主要是为了跟CPU的字长一致,目的当然是提高处理速度。 Java面向对象有哪些特征?主要有四个特征:抽象,封装,继承和多态。 抽象的目的是忽略与主题无关的其他信息,使用abstract关键字修饰,规定抽象方法只能为public/protected,被修饰的类不能被实例化,只允许通过继承的方式来实现。 封装的意思就是想让你看到就让你看到不想让你看到就不让你看到,使用private关键字实现,当你需要对属性进行修改的时候就使用类中的get/set方法,使用public关键字。这是出于安全和易用性方面的考虑。 继承的意义在于不需要重复造轮子,子类继承父类就可以得到除了private之外的父类的全部属性和方法(父类的构造方法除外)。需要知道的是Java只支持单继承,这是出于对继承链可能会出现过于复杂的情况的设计方案,如果想实现类似C++语言的多继承,可以使用接口来实现。还需要注意这几点,如果没有指定父类,那么类的直接父类是java.lang.Object;一般继承会导致重写,子类有时候会需要重写父类的方法,在重写时必须保证方法名和形参列表相同,返回值类型和异常类型子类需要小于父类;访问权限,子类需要大于父类。 多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用只有在程序运行期间才会确定,在Java中通过继承的方式来实现多态,即父类接口引用变量指向子类或实现类的实例对象,这样程序调用的方法在运行期才会动态绑定引用变量所指向的具体实例对象的方法,也就是内存里正在运行的对象方法。。比如公司规定十点上班工作,但并不会对程序员说你要敲代码,并不会对HR说你要检查邮件这个工作的具体实现。需要注意的是多态是方法的多态而不是属性的多态,多态是在继承的基础上实现的。 接口和抽象的区别是什么?两者都是Java面向对象的重要实现。它们都声明方法而不去实现,本质的区别在于抽象类是一个类,而接口是其他的类型,在OC中都没有接口这一说,而是使用protocol。抽象类除了不能实例化之外跟普通的类没有区别,而接口完全不存在方法的实现,不能有构造器,只能使用public访问修饰符,没有main方法等。接口提供抽象方法,类通过interface关键字对接接口,重写抽象方法实现对应业务逻辑以此对外提供服务。比如Map接扣作为一个容器就会提供put方法来往容器中填充值,get方法获取容器中某一个值,size属性获取容器大小,remove方法来删除容器中的值。接口除了做规范之外还是多继承在Java中的解决方案,另外接口也是各种框架和API的实现,比如RedisTemplate就是封装了jedis,如果在项目中使用redis,直接通过注入RedisTemplate接口就可以完成对redis的操作。 已经有基本类型了,为什么还需要包装类型呢?Java提供了八种基本类型,每一种类型都会有一个对应的包装类型,比如boolean-Boolean,JVM会在两者之间自动转换,这是JDK1.5做的改变。 Integer i = 1; //自动装箱,编译时会调用Integer.valueOf(1) int j = i; //自动拆箱,编译时调用intValue(); 值得注意的是自动装箱时系统会创建缓存,并将当前数据添加到缓存中,有两个作用,第一是为了缓解使用包装类型导致数据存储会略微变慢的问题,第二是解决了包装类型判断是否相等的问题。 Java是一门面向对象的语言,基本数据类型并不具备面向对象的特征,这会导致数据存储的问题,例如在处理空值的时候,使用Integer时需要判断null,使用int的时候需要判断0,而在数据库中通常默认值为0。这会导致在数据库中存储id的时候,id类型为bigint,当控制类方法的接收值为long而不是Long的话会报错。使用Long表示类的ID的时候,在需要判断类是否存在只需要判断为null就可以了,而且使用包装类型就可以通过其提供的方法MAX和MIN获取最大值和最小值等。 说一下"=="和equals方法究竟有什么区别?==用于判断两个变量是否相等。变量可以分为基本数据类型和引用数据类型,如果是引用数据类型需要比较引用的内存首地址,如果是基本数据类型直接比较值。 equals方法是判断两个对象的某些特征是否一致,通过重写对象的equals方法。 如何理解?通过观察源码会发现,equals方法会首先判断两个比较值类型是否一致,然后再比较数值或字符,例如Integer类型会自动拆箱为int类型进行比较,String会将字符串拆分成字符。 讲一下String和StringBuilder的区别(final)?StringBuffer和StringBuilder的区别?java提供了三个类String、StringBuilder和StringBuffer来表示和操作字符串。字符串即是由多个字符(char)的集合。 String是内容不可变的字符串(private final char value[]) StringBuilder和StringBuffer继承自AbstractStringBuilder类(char[] value); 因此拼接字符串的时候: String:String s = "a"+"b"; StringBuilder sb = new StringBuilder(); sb.apend("a").apend("c") 拼接字符串的时候不能使用String进行拼接,要使用StringBuilder和StringBuffer。前者效率高但线程不安全,后者效率低但线程安全。 简单说一下java中的集合 java中的集合主要分为value和key-value两种。 存储值分类list和set,list重复有序,set不可重复无序。并且set根据equals和hashcode判断,如果对象存储在set中,则必须重写这两个方法。 存储键值在java中是称之为map,在OC语言中叫字典。 List常用的ArrayList和LinkedList的区别和使用场景? ArrayList底层使用数组(private transient Object[] elementData;) LinkedList底层使用链表(transient Node<E> first; transient Node<E> last;) 数组是一块连续的内存,因此插入和删除的时候需要移动内存。由于有这个特点所以说数组查询元素快,插入和删除删除慢。 链表的原理是在当前元素中存放上一个和下一个元素的地址,查询时从头部开始一个个找,因此查询效率慢,由于做修改的时候不需要做内存移动操作,只需要改变引用指向即可完成,所以插入和删除操作效率高。 不难看出链表和数组是相反的,所以它们的使用场景就呼之欲出了,而由于数据库操作的特殊性(查询占90),所以一般我们会选择ArrayList做数据保存的容器。 讲一下HashMap和 HashTable的区别?HashTable和ConcurrentHashMap的区别? 首先HashTable是不可以使用null作为key或者value的,HashTable在存储数据的时候会返回synchronized。因此可以得出结论HashTable安全但效率不高。 如果想既效率高又安全,可以使用ConcurrentHashMap并发容器的方式,原理是将整个Map分成N个Segment(类似HashTable不加锁),提供相同的线程安全,但是效率提升N倍默认为16倍。 实现一个拷贝文件的工具类使用字节流还是字符流? 字节流和字符流都可以实现对文件的拷贝,如果确认不包含例如图片和音频这样特殊的文件,使用字符流即可,否则应该使用字节流。 线程的几种实现方式,启动方式? 两种实现方式:继承Thread类和实现Runnable接口。一般采用实现接口的方式,因为java只支持单继承。 Thread thread = new Thread(new MyThread());//MyThread类继承了Thread对象或Runnable接口 thread.setName("xiaoming");//通过设置线程名称来区分线程 thread.start();//通过start()方法来启动线程,但实际执行的方法是run方法。run()方法是Thread类和Runnable接口自带的方法,需要重写和实现run()。 线程池的作用 线程过多的话会导致系统运行缓慢甚至崩溃,所以需要限制线程的个数 线程池如果每次都创建或者销毁会导致资源的浪费 什么是设计模式?常用的设计模式有哪些? 设计模式是前人经验所得的可以反复使用,解决特定问题的设计方法。 单例模式是最常见的设计模式之一,它的作用是保证某一实例的唯一性。具体实现就是在类中定义一个实例对象并提供一个公开方法获取该实例,然后将构造器私有化,如果需要使用该实例的话,只能通过提供的公开方法而不能new出这个类,这样每次得到的实例就是同一个实例。单例分为懒加载和立即加载两种模式,懒加载在创建对象的时候就加载实例,立即加载在需要的时候才加载实例。 工厂模式,SpringIoC中的BeanFactory,MyBatis中的SqlSessionFactory就都是工厂模式的实现 代理模式,SpringAOP是通过动态代理实现 观察者模式,Spring中的listener实现ApplicationListener 模板模式,Spring集成了JdbcTemplate、RedisTemplate、SolrTemplate、JmsTemplate 适配器模式,SpringMVC中的处理器映射器HandlerMapper 二、J2EE部分 说一下你对servlet的理解?或者servlet是什么?Java Servlet是使用J2EE服务端程序,后端代码通过实现Servlet接口并重写HTttpServlet的doGet/doPost方法来进行对数据库和浏览器之间的交流,Servlet程序需要运行在支持Java程序的应用服务器中,比如tomcat,jetty等。 简单说一下servlet的生命周期?Servlet是一个接口规范,所以有比较明确的生存期定义,接口中的init,service和destory方法进行表述。 Servlet API中forward()与redirect()的区别?forward就是转发,是服务端行为因此只发送一次请求也不会改变url地址,redirect是重定向,是客户端行为会改变url地址并且发送两次请求 JSP和Servlet有哪些相同点和不同点?JSP是Servlet的扩展,所有的jsp文件都会被编译成一个继承自HttpServlet的类,因为servlet输出html比较麻烦,所以设计出jsp。 JSP有哪些内置对象?作用分别是什么? 九个内置的对象: request 用户端请求,此请求会包含来自GET/POST请求的参数 response 网页传回用户端的回应 pageContext 网页的属性是在这里管理 session 与请求有关的会话期 application servlet正在执行的内容 out 用来传送回应的输出 config servlet的构架部件 page JSP网页本身 exception 针对错误网页,未捕捉的例外 四大作用域: pageContext 整个page页面 request(HttpServletRequest) service方法 session(HttpSession) 第一次调用request.getSession()方法时 application(ServletContext) 整个WEB应用程序 说一下Session和Cookie的区别?你在项目中都有哪些地方使用了?session和cookie都是HTTP的会话跟踪技术,是为了解决HTTP无状态的特性而设计的技术。cookie在客户端浏览器记录信息认证身份,session在服务端记录信息确认身份。session通过在cookie中存放的sessionId来保证信息的一致性。 session和cookie的区别如下 由于cookie数据保存在浏览器中,因此有安全和数据限制的问题,考虑到这种情况应该使用session保存数据 session数据存在服务器上,当访问比较多的情况下会耗费服务器资源,考虑到这种情况应该使用cookie购物车是最好的cookie技术实现场景,用户登录信息的存储是最好的session技术实现场景。 我在做用户注册生成短信验证码和solr异步删除索引库数据,静态页面生成的时候使用过jmsTemplate.send()方法,该方法中有一个内部类(new MessageCreator()),此类中接收session参数,然后通过这个session创建消息实例设置消息并返回。 HTTP中GET和POST请求的区别用户通过不同的请求方式完成对资源的不同操作,比如PUT请求就是代表对请求资源的增加,DELETE请求就是对请求资源的删除。为了方便开发,一般我们只使用GET和POST方式就可以了。两者本质上都是TCP链接,区别在于: get请求时,地址栏会显示请求信息,以?开头,多个参数以&连接,而post请求在request body中 get请求由于浏览器对地址长度的限制而导致传输的数据有限,post则没有这个限制 由于请求信息会暴露所以get请求会有安全隐患 get产生一个TCP数据包,浏览器会将http header和data数据一起发送,等待服务器响应200并返回数据;post请求产生两个数据包,浏览器会发送header,等待服务器响应100 continue,浏览器才会发送data,最后等待服务器响应200和请求的数据 对于get和post的区别,有一个比较有趣的比喻。get传递数据如同写在脸上,post传递数据如同方法肚子里,脸上自然不能放太多东西也不能放隐私的东西,而肚子里就无所谓了。

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

Android 图片相关整理

目录介绍 0.思考问题及解决方案 1.加载图片的压缩处理技术 2.网络url图片转换Bitmap保存到本地 2.1 直接通过http请求网络图片通过流转化成Bitmap 2.2 使用第三方库glide将网络图片转化为Bitmap 3.保存bitmap图片到本地文件夹 4.实现带有圆角的图片 4.1 使用glide处理图片圆角的逻辑 4.2 自定义带有圆角的ImageView 5.毫无满仓轮播图背景做高斯模糊 5.1 高斯模糊实现原理 5.2 高斯模糊实现的代码 5.3 高斯模糊可能会造成的崩溃 5.4 高斯模糊参考案例 关于链接 1.技术博客汇总 2.开源项目汇总 3.生活博客汇总 4.喜马拉雅音频汇总 5.程序员聊天笔记汇总 5.其他汇总 0.思考问题及解决方案 0.1.0 图片压缩的技术是什么,原理如何理解? 0.1.1 为什么保存图片,切割图片圆角需要将图片转化成bitmap? 0.1.2 对于从网络下载图片,可以采用什么方式?为什么glide相比从网络直接请求更加高效? 0.1.3 图片背景滑动高斯模糊的原理是什么,是否影响性能? 0.1.4 bitmap如何避免被回收?如果回收了,怎么避免出现使用bitmap崩溃 0.1.5 为什么设置高斯模糊需要放在子线程中处理,不这样做会有什么影响? 1.加载图片的压缩处理技术 1.1 压缩技术步骤 1.1.1 科学计算图片所需的采样比例 1.1.2 设置图片加载的渲染模式为Config.RGB_565,能降低一半内存 1.1.3 对bitmap进行质量压缩 1.2 代码如下所示 /** * 根据路径获得突破并压缩返回bitmap用于显示 * @return Bitmap */ public static Bitmap getSmallBitmap(String filePath, int newWidth, int newHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); //设置只解析图片的边界参数,即宽高 options.inJustDecodeBounds = true; //options.inSampleSize = 2; BitmapFactory.decodeFile(filePath, options); // Calculate inSampleSize //科学计算图片所需的采样比例 options.inSampleSize = calculateInSampleSize(options, newWidth, newHeight); //设置图片加载的渲染模式为Config.RGB_565,能降低一半内存,但是会影响图片质量 options.inPreferredConfig = Bitmap.Config.RGB_565; // Decode bitmap with inSampleSize set //关闭标记,解析真实的图片 options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); //质量压缩 Bitmap newBitmap = compressImage(bitmap, 500); if (bitmap != null){ bitmap.recycle(); } return newBitmap; } /** * 计算图片的缩放值 */ private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { // Calculate ratios of height and width to requested height and // width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will // guarantee // a final image with both dimensions larger than or equal to the // requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } /** * 质量压缩 * @param image * @param maxSize */ private static Bitmap compressImage(Bitmap image, int maxSize){ ByteArrayOutputStream os = new ByteArrayOutputStream(); // scale int options = 80; // Store the bitmap into output stream(no compress) image.compress(Bitmap.CompressFormat.JPEG, options, os); // Compress by loop while ( os.toByteArray().length / 1024 > maxSize) { // Clean up os os.reset(); // interval 10 options -= 10; image.compress(Bitmap.CompressFormat.JPEG, options, os); } Bitmap bitmap = null; byte[] b = os.toByteArray(); if (b.length != 0) { bitmap = BitmapFactory.decodeByteArray(b, 0, b.length); } return bitmap; } 2.网络url图片转换Bitmap保存到本地 2.1 直接通过http请求网络图片通过流转化成Bitmap 2.1.1 直接通过网络请求将网络图片转化成bitmap 经过测试,请求8张图片,耗时毫秒值174 如果是服务器响应速度一般,耗时需要2秒【正式接口】 /** * 请求网络图片转化成bitmap * @param url url * @return 将url图片转化成bitmap对象 */ private static long time = 0; public static Bitmap returnBitMap(String url) { long l1 = System.currentTimeMillis(); URL myFileUrl = null; Bitmap bitmap = null; HttpURLConnection conn = null; InputStream is = null; try { myFileUrl = new URL(url); } catch (MalformedURLException e) { e.printStackTrace(); } try { conn = (HttpURLConnection) myFileUrl.openConnection(); conn.setConnectTimeout(10000); conn.setReadTimeout(5000); conn.setDoInput(true); conn.connect(); is = conn.getInputStream(); bitmap = BitmapFactory.decodeStream(is); } catch (IOException e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); conn.disconnect(); } } catch (IOException e) { e.printStackTrace(); } long l2 = System.currentTimeMillis(); time = (l2-l1) + time; LogUtils.e("毫秒值"+time); //保存 } return bitmap; } 2.2 使用第三方库glide将网络图片转化为Bitmap /** * 请求网络图片转化成bitmap */ private static long times = 0; public static void glideBitmap(Context context,String url){ final long l1 = System.currentTimeMillis(); Glide.with(context) .load(url) .asBitmap() //设置缓存 .diskCacheStrategy(DiskCacheStrategy.ALL) .into(new SimpleTarget<Bitmap>() { @Override public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { long l2 = System.currentTimeMillis(); times = (l2-l1) + times; LogUtils.e("毫秒值"+times); //请求8张图片,耗时毫秒值98 } }); } 3.保存bitmap图片到本地文件夹 /** * 保存图片至自定义路径,刷新相册 */ public static void saveImageToFile(Context context, Bitmap bmp) { // 首先保存图片,这个路径可以自定义 File appDir = new File(Environment.getExternalStorageDirectory(), "yc"); // 测试由此抽象路径名表示的文件或目录是否存在 if (!appDir.exists()) { //如果不存在,则创建由此抽象路径名命名的目录 //noinspection ResultOfMethodCallIgnored appDir.mkdir(); } // 然后自定义图片的文件名称 String fileName = System.currentTimeMillis() + ".jpg"; // 创建file对象 File file = new File(appDir, fileName); try { FileOutputStream fos = new FileOutputStream(file); bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); } // 其次把文件插入到系统图库 try { MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), fileName, null); } catch (FileNotFoundException e) { e.printStackTrace(); } // 最后通知图库更新 Intent intent = new Intent(); intent.setAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(Uri.parse("file://" + file.getAbsoluteFile())); context.sendBroadcast(intent); } 4.实现带有圆角的图片 4.1 使用glide处理图片圆角的逻辑 /** * 加载带有圆角的矩形图片 用glide处理 * * @param path 路径 * @param round 圆角半径 * @param resId 加载失败时的图片 * @param target 控件 */ public static void loadImgByPicassoWithRound(final Context activity, String path, final int round, int resId, final ImageView target) { if (path != null && path.length() > 0) { Glide.with(activity) .load(path) .asBitmap() .placeholder(resId) .error(resId) //设置缓存 .diskCacheStrategy(DiskCacheStrategy.ALL) .into(new BitmapImageViewTarget(target) { @Override protected void setResource(Bitmap resource) { super.setResource(resource); RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory .create(activity.getResources(), resource); //设置绘制位图时要应用的角半径 circularBitmapDrawable.setCornerRadius(round); target.setImageDrawable(circularBitmapDrawable); } }); } } 4.2 自定义带有圆角的ImageView 使用BitmapShader实现圆形、圆角图片 具体看:https://github.com/yangchong211/YCPaiDian 中的libimage自定义imageView 5.毫无满仓轮播图背景做高斯模糊 5.1 高斯模糊实现原理 前沿【摘自网络】:在Android平台上进行模糊渲染是一个相当耗CPU也相当耗时的操作,一旦处理不好,卡顿是在所难免的。考虑到效率,渲染一张图片最好的方法是使用OpenGL,其次是使用C++/C,使用Java代码是最慢的。但是Android推出RenderScript之后,我们就有了新的选择,测试表明,使用RenderScript的渲染效率和使用C/C++不相上下,但是使用RenderScript却比使用JNI简单地多! 原理步骤如下所示: a.压缩图片,可以质量压缩,也可以宽高压缩 b.创建RenderScript内核对象 c.创建一个模糊效果的RenderScript的工具对象 d.设置相关参数,具体看代码…… 实现思路:先将图片进行最大程度的模糊处理,再将原图放置在模糊后的图片上面,通过不断改变原图的透明度(Alpha值)来实现动态模糊效果。 5.2 高斯模糊实现的代码 5.2.1 设置高斯模糊代码 /** * 设置模糊背景 */ private void setBlurBackground(int pos) { //获取轮播图索引pos处的图片 Integer integer = pagerAdapter.getBitmapHashMap().get(pos); Resources res = this.getResources(); Bitmap bitmap= BitmapFactory.decodeResource(res, integer); //压缩图片 final Bitmap image = BitmapUtils.compressImage(bitmap); if (bitmap != null) { if (mBlurRunnable != null) { mIvBlurBackground.removeCallbacks(mBlurRunnable); } mBlurRunnable = new Runnable() { @Override public void run() { //压缩图片,宽高缩放 Bitmap blurBitmap = BlurBitmapUtils.getBlurBitmap( mIvBlurBackground.getContext(), image, 15); ViewSwitchUtils.startSwitchBackgroundAnim(mIvBlurBackground, blurBitmap); } }; mIvBlurBackground.postDelayed(mBlurRunnable, 100); } } 5.2.2 RenderScript图片高斯模糊 /** * RenderScript图片高斯模糊 */ public class BlurBitmapUtils { /** * 建议模糊度(在0.0到25.0之间) */ private static final int SCALED_WIDTH = 100; private static final int SCALED_HEIGHT = 100; /** * 得到模糊后的bitmap * @param context 上下文 * @param bitmap bitmap * @param radius 半径 * @return */ public static Bitmap getBlurBitmap(Context context, Bitmap bitmap, int radius) { // 将缩小后的图片做为预渲染的图片。 Bitmap inputBitmap = Bitmap.createScaledBitmap(bitmap, SCALED_WIDTH, SCALED_HEIGHT, false); // 创建一张渲染后的输出图片。 Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap); // 创建RenderScript内核对象 RenderScript rs = RenderScript.create(context); // 创建一个模糊效果的RenderScript的工具对象 ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); // 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间。 // 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去。 Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap); Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap); // 设置渲染的模糊程度, 25f是最大模糊度 blurScript.setRadius(radius); // 设置blurScript对象的输入内存 blurScript.setInput(tmpIn); // 将输出数据保存到输出内存中 blurScript.forEach(tmpOut); // 将数据填充到Allocation中 tmpOut.copyTo(outputBitmap); return outputBitmap; } } 5.2.3 设置高斯模糊背景View动画过渡效果 /** * 图片背景切换动画帮助类,设置View动画 */ public class ViewSwitchUtils { static void startSwitchBackgroundAnim(ImageView view, Bitmap bitmap) { Drawable oldDrawable = view.getDrawable(); Drawable oldBitmapDrawable ; TransitionDrawable oldTransitionDrawable = null; if (oldDrawable instanceof TransitionDrawable) { oldTransitionDrawable = (TransitionDrawable) oldDrawable; oldBitmapDrawable = oldTransitionDrawable.findDrawableByLayerId(oldTransitionDrawable.getId(1)); } else if (oldDrawable instanceof BitmapDrawable) { oldBitmapDrawable = oldDrawable; } else { oldBitmapDrawable = new ColorDrawable(0xffc2c2c2); } if (oldTransitionDrawable == null) { oldTransitionDrawable = new TransitionDrawable(new Drawable[]{oldBitmapDrawable, new BitmapDrawable(bitmap)}); oldTransitionDrawable.setId(0, 0); oldTransitionDrawable.setId(1, 1); oldTransitionDrawable.setCrossFadeEnabled(true); view.setImageDrawable(oldTransitionDrawable); } else { oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(0), oldBitmapDrawable); oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(1), new BitmapDrawable(bitmap)); } oldTransitionDrawable.startTransition(1000); } } 5.3 高斯模糊可能会造成的崩溃 5.3.1 崩溃日志 开发回收bitmap引发Canvas: trying to use a recycled bitmap错误处理 5.3.2 抛该异常的原因分析 如果代码已经不再需要使用Bitmap对象了,就可以释放了。释放内存以后,就不能再使用该Bitmap对象了,如果再次使用,就会抛出异常。所以一定要保证不再使用的时候释放。 5.3.3 解决该问题的办法 使用缓存 5.4 高斯模糊参考案例 Android 图片高斯模糊解决方案:https://www.jianshu.com/p/02da487a2f43 关于我的博客 我的个人站点:www.yczbj.org,www.ycbjie.cn github:https://github.com/yangchong211 知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts 简书:http://www.jianshu.com/u/b7b2c6ed9284 csdn:http://my.csdn.net/m0_37700275 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/ 开源中国:https://my.oschina.net/zbj1618/blog 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1 邮箱:yangchong211@163.com 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles

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

Python学习资源整理

官方链接 Python官网 Pip 在线资源 菜鸟教程 慕课网 极客学院 伯乐在线 网易云课堂 实验楼 Web开发 Django Flask Sanic Tornado webpy Bottle 网页爬虫 网页抓取 urllib Requests 网页解析 BeautifulSoup lxml PyQuery 自动化框架 Selenium 爬虫框架 Scrapy PySpider 数据科学 NumPy Pandas Matplotlib SciPy 图像识别 OpenCV 自然语言 NLTK 机器学习 Scikit-learn TensorFlow Keras 公众号 Python那些事 Python开发者 Python绿色通道 欢迎大家留言补充

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

python库使用整理

1. 环境搭建 l Python安装包:www.python.org l Microsoft Visual C++ Compiler for Python l pip(get-pip.py):pip.pypa.io/en/latest/installing.html n pip install + 安装包 --安装包(.whl,.tar.gz,.zip) n pip uninstall + 安装包 --卸载包 n pip show --files + 安装包 --查看已安装包信息 n pip list outdated --查看待更新包信息 n pip install -U + 安装包 --升级包 n pip search + 安装包 --搜索包 n pip help --显示帮助信息 l Anaconda:continuum.io/downloads n conda install + 安装包 n conda uninstall + 安装包 l 一些常用包:www.lfd.uci.edu/~gohlke/pythonlibs/ n re:正则匹配;os:文件操作;random:随机数;time:时间戳 n requests:网页交互(get & post) n beautifulsoup4:用于规范化的静态网页的分析 nmysqlclient、PyMySQL:Mysql数据库操作接口 n numpy+mkl:矩阵运算 n scipy:科学计算(插值,积分,优化,图像处理,特殊函数) n matplotlib:图形绘制 nscikit-learn:机器学习库 n jieba、smallseg:中文分词https://pypi.python.org/pypi/jieba/ n pandas:大型数据处理 n nltk:提供50多个语料库和词典资源(分类、分词、词干提取、解析、语义推理) n Pattern:拥有一系列的自然语言处理工具,词性标注工具(Part-Of-Speech Tagger),N元搜索(n-gram search),情感分析(sentiment analysis),WordNet,也支持机器学习的向量空间模型,聚类,向量机。 n TextBlob:处理文本数据(词性标注、名词短语抽取、情感分析、分类、翻译) n Gensim:用于对大型语料库进行主题建模、文件索引、相似度检索等,可以处理大于内存的输入数据 n PyNLPI n spaCy:一个商业的开源软件,结合了Python和Cython的NLP工具 n Polyglot:支持大规模多语言应用程序的处理(165种语言的分词,196种语言的辨识,40种语言的专有名词识别,16种语言的词性标注,136种语言的情感分析,137种语言的嵌入,135种语言的形态分析,以及69种语言的翻译) n MontyLingua:免费的、功能强大的、端到端的英文处理工具,适用于信息检索和提取,请求处理,问答系统,能词性标注和实体识别一些语义信息。 n BLLIP Parser:集成了生成成分分析器和最大熵排序的统计自然语言分析器 n Quepy:提供了将自然语言问题转换成为数据库查询语言中的查询 n PIL:图像处理 n xgboost(eXtreme Gradient Boosting):梯度上升算法 2. 常用命令 l python XXX.py --运行程序 l python setup.py build --编译,须在setup.py所在目录下 l python setup.py install --安装,同上 l python setup.py sdist --制作分发包,同上 l python setup.py bdist_wininst --制作windows下的分发包,同上 3. 标准定义 #!usr/bin/python # -*- coding: utf-8 -*- # encoding=utf-8 from distutils.core import setup import sys reload(sys) sys.setdefaultencoding('utf8') # 安装包打包 setup(name="example", version="v1.0.0", description="setup_examples", author="SweetYu", py_modules=['文件夹1.文档1','文件夹1.文档2','文件夹2.文档3']) #类的定义 class A: __count = 0 # 私有类变量 def __init__(self, name): self.name = name # 公有成员变量 A.__count += 1 @classmethod def getCount(cls): # 类函数 return cls.__count def getName(self): # 成员函数 return self.name if __name__ == '__main__': main() 4. json、string、random、re 正则表达式(Res,regex pattens) l 元符号 .表示任意字符 []用来匹配一个指定的字符类别 ^ 取非 * 前一个字符重复0到无穷次 $ 前一个字符重复1到无穷次 ?前一个字符重复0到1次 {m}前一个字符重复m次 l 特殊匹配 \d 匹配任何十进制数,相当于类 [0-9]。 \D 匹配任何非数字字符,相当于类 [^0-9] \s 匹配任何空白字符,相当于类 [ fv] \S 匹配任何非空白字符,相当于类 [^ fv] \w 匹配任何字母数字字符,相当于类 [a-zA-Z0-9_] \W 匹配任何非字母数字字符,相当于类 [^a-zA-Z0-9_] import json, os, re, time import string, random obj = [[1,2,3],123,123.123,'abc',{'key1':(1,2,3),'key2':(4,5,6)}] encode_obj = json.dumps(obj, skipkeys=True, sort_keys=True) #将对象转换成字符串 decode_obj = json.loads(encode_obj) #将字符串转换成对象 random.randint(0,255) #获取0~255范围内的整数 field = string.letters + string.digits #大小写字母+数字 random.sample(field,5) #获取长度为5的field范围内的随机字符串 #文件处理 fp = open(filename,"w", encoding='utf-8-sig') # 'w', 'w+', 'r', 'r+', 'a', 'a+' fp.write(unicode("\xEF\xBB\xBF", "utf-8")) #写到文件开头,指示文件为UTF-8编码 fp.close() m = re.search("^ab+","asdfabbbb") # m.group() à 'abbbb' re.findall("^a\w+","abcdfa\na1b2c3",re.MULTILINE) re.findall("a{2,4}","aaaaaaaa") # ['aaaa', 'aaaa'] re.findall("a{2,4}?","aaaaaaaa") # ['aa', 'aa', 'aa', 'aa'] re.split("[a-zA-Z]+","0A3b9z") # ['0', '3', '9', ''] m = re.match("(?P<first_name>\w+) (?P<last_name>\w+)","sam lee") > m.group("first_name") # 'sam' > m.group("last_name") # 'lee' re.sub('[abc]', 'o', 'caps rock') # 'cops rook' 5. os、time 在Python中,通常有这几种方式来表示时间: 1)时间戳 :从1970年1月1日00:00:00开始按秒计算的偏移量,如:time(),clock(),mktime() 2)格式化的时间字符串,如:strftime () 3)struct_time元组:如:gmtime()【UTC时区】,localtime()【当前时区】,strptime() import os, time time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X') time.strftime("%Y-%m-%d %X", time.localtime()) time.localtime(1304575584.1361799) #(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=14, tm_min=6, tm_sec=24, tm_wday=3, tm_yday=125, tm_isdst=0) time.sleep(s) #线程休眠s秒 #获取文件创建时间 例:1483882912.37 Sun Jan 08 21:41:52 2017 time.ctime(os.path.getctime(fileName)) os.path.exists(fileName) #是否存在某一文件 os.chdir(dir) #修改当前目录 os.getcwd() #获取当前目录 os.listdir(dir) #返回指定目录下的所有文件和目录名 os.remove(fileName) #删除一个文件 os.makedirs(dir/fileName) #生成多层递规目录 os.rmdir(dir) #删除单级目录 os.rename(oldName, newName) #重命名文件 > os.sep #当前平台下路径分隔符 > os.linesep #给出当前平台使用的行终止符 > os.environ #获取系统环境变量 os.path.abspath(path) #显示该路径的绝对路径 os.path.dirname(path) #返回该路径的父目录 os.path.isfile(path) #如果path是一个文件,则返回True os.path.isdir(path) #如果path是一个目录,则返回True os.path.splitext(fileName) #获得(文件名,文件名后缀) os.stat() #获取文件或者目录信息 os.path.join(dir,fileName) #连接目录与文件名或目录 结果为path/name 6. requests import requests session = requests.session() url = 'https://api.github.com/some/endpoint' params = {'some': 'data'} headers = {'content-type': 'application/json'} files = {'file': open('report.xls', 'rb')} cookies = dict(cookies_are='working') r = session.post(url, data = json.dumps(params), headers = headers, files = files, cookies = cookies, allow_redirects = False, timeout = 0.001) # get、put、delete、options、head > r.status_code # requests.codes.ok > r.url > r.encoding > r.text > r.content > r.headers # r.headers['Content-Type']或 r.headers.get('content-type') > r.history 7. beautifulsoup4 BeautifulSoup将HTML文档转换成一个树形结构,每个节点都是Python对象,所有对象可以归纳为4种:Tag、NavigableString、BeautifulSoup、Comment。 当前结点: .name:标签名 .attr:标签的属性集合(json) .string:标签内容 .strings:标签对象包含的多个内容列表(list) .stripped_strings:去除多余空白内容后的多个内容列表(list) 直接/所有子节点: .contents .children .descendants (所有)父节点: .parent .parents 兄弟节点: .next_sibling .previous_sibling 前后节点【不分层次】: .next_element .next_elements .previous_element .previous_elements 搜索文档树 find_all、find find_parents、find_parent find_next_siblings、find_next_sibling find_previous_siblings、find_previous_sibling find_all_next、find_next find_all_previous、find_previous select name参数:标签名、正则表达式、列表、True(匹配任何值)、方法 keyword参数:class、id、href等标签属性 text 参数:标签内容 limit参数:返回列表的大小 recursive 参数,是否仅包含直接子结点(True/False) 标签名不加任何修饰,类名前加点,id名前加 # import re from bs4 import BeautifulSoup def has_class_but_no_id(tag): return tag.has_attr('class') and not tag.has_attr('id') soup = BeautifulSoup(html) > soup.prettify() > soup.find_all(has_class_but_no_id) > soup.find(re.compile("^b")) > soup.select('a[class="sister"]') if type(soup.a.string)==bs4.element.Comment: print(soup.a.string) #遍历某一对象的非注释字符串 for str in soup.stripped_strings: print(repr(str)) 8. numpy 常用属性:Itemsize(单个元素字节数)、size(元素个数)、shape、ndim(维数)、dtype、axis=0(列)/1(行) 常用函数:max、min、sum、sin、floor(向下取整)、dot(矩阵相乘)、exp、.vstack(纵向合并)、hstack(横向合并) 矩阵运算:transpose(转置)、trace(迹)、eig(特征值和特征向量)、inner(内积)、outer(外积) import numpy as np import numpy.linalg as nplg a = np.array([[1,2],[3,4]] , dtype=np.int32) #[[1 2][3 4]] nplg.eig(a) #矩阵A的特征向量和特征值 b = np.arange(6).reshape(2,3) #[[01][2 3][4 5]] c = np.linspace(1,3,9) #[1. 1.25 1.5 1.75 2. 2.25 2.5 2.75 3.] d = np.zeros((1,3)) # ones全1矩阵;eyes 单位矩阵;zeros 全0矩阵 e = d.repeat(2,axis=0) #[[0 0 0][0 0 0]] np.merage(a,b) #合并数据 a.tofile("a.bin") f = np.fromfile("a.bin", dtype= a.dtype) f.shape = a.shape np.save("a.npy", a) g = np.load("a.npy") 9. scipy 10. sklearn 1) Scikit-learn本身不支持深度学习和加强学习,也不支持GPU加速,不支持图模型和序列预测; 2) Scikit-learn从来不做除机器学习领域之外的其他扩展; 3) Scikit-learn从来不采用未经广泛验证的算法; 数据预处理 特征提取:将输入数据转换为具有零均值和单位权方差的新变量 归一化:将文本或图像数据转换为可用于机器学习的数字变量 from sklearn.preprocessing import * # z-score标准化:减去均值,除以标准 X = StandardScaler().fit_transform(X) # 最小-最大规范化:缩放至特定范围 X = MinMaxScaler().fit_transform(X) X = MaxAbsScaler().fit_transform(X) # 数据归一化/规范化 X = Normalizer(X, norm='l2').fit_transform(X) # norm可取值l1,l2,max # 数值特征二值化 X = Binarizer(threshold=1.1).fit_transform(X) # threshold为阈值 # 类别数据编码,OneHot编码:OneHotEncoder # 标签二值化:将类别特征转换为多维二元特征,并将每个特征扩展成用一维表示 label_binarize([1, 6], classes=[1, 2, 4, 6]) # 输出[1, 0, 0, 0],[0, 0, 0, 1] # 类别编码 LabelEncoder().fit_transform(['A','A','b','c']) # 输出[0, 0, 1, 2] # 缺失值填补 imp = Imputer(missing_values='NaN', strategy='mean', axis=0) imp.fit_transform([[1, 2], [np.nan, 3], [7, 6]])) #[[1, 2], [4, 3], [7, 6]] # 生成多项式特征 例:[a,b] -> [1,a,b,a^2,ab,b^2] PolynomialFeatures(2).fit_transform(X) # 增加伪特征 FunctionTransformer(np.log1p).fit_transform([[0, 1], [2, 3]]) 分类算法 线性:朴素贝叶斯(NB)、K-最近邻(KNN)、逻辑回归(LR) n 训练和预测的效率较高,但对特征的依赖程度也高 n 需在特征工程上尽量对特征进行选择、变换或者组合,使得特征具有线性可分性 非线性:随机森林(RF)、决策树(DT)、梯度提升(GBDT)、支持向量机-交叉验证(SVM-CV)、多层感知机(MLP)神经网络 n 可建模复杂的分类面,能更好的拟合数据。 # NB(Multinomial Naive Bayes) Classifier from sklearn.naive_bayes import MultinomialNB model = MultinomialNB(alpha=0.01) # KNN Classifier from sklearn.neighbors import KNeighborsClassifier model = KNeighborsClassifier() # LR(Logistic Regression) Classifier from sklearn.linear_model import LogisticRegression model = LogisticRegression(penalty='l2') # RF(Random Forest) Classifier from sklearn.ensemble import RandomForestClassifier model = RandomForestClassifier(n_estimators=8) # DT(Decision Tree) Classifier from sklearn import tree model = tree.DecisionTreeClassifier() # GBDT(Gradient Boosting Decision Tree) Classifier from sklearn.ensemble import GradientBoostingClassifier model = GradientBoostingClassifier(n_estimators=200) # SVM Classifier from sklearn.svm import SVC model = SVC(kernel='rbf', probability=True) # SVM Classifier using CV(Cross Validation) from sklearn.grid_search import GridSearchCV from sklearn.svm import SVC model = SVC(kernel='rbf', probability=True) param_grid = {'C': [1e-3, 1e-2, 1e-1, 1, 10, 100, 1000], 'gamma': [0.001, 0.0001]} grid_search = GridSearchCV(model, param_grid, n_jobs = 1, verbose=1) grid_search.fit(train_x, train_y) best_parameters = grid_search.best_estimator_.get_params() for para, val in best_parameters.items(): print para, val model=SVC(kernel='rbf',C=best_parameters['C'],gamma=best_parameters['gamma'],probability=True) # MLP Classifier from sklearn.neural_network import MLPClassifier clf=MLPClassifier(solver='lbfgs',alpha=1e-5,hidden_layer_sizes=(5,2),random_state=1) #建立模型 model.fit(train_x, train_y) #预测与评价 from sklearn import metrics predict = model.predict(test_x) precision = metrics.precision_score(test_y, predict) recall = metrics.recall_score(test_y, predict) accuracy = metrics.accuracy_score(test_y, predict) 回归分析 支持向量回归(SVR) 贝叶斯回归、内核岭回归(KR)、高斯回归 岭回归:通过增加惩罚函数来判断、消除特征间的共线性 Lasso回归(least absolute shrinkage and selection operator,最小绝对值收缩和选择算子) 弹性网络(Elastic Net):使用L1和L2先验作为正则化矩阵的线性回归模型 最小角回归(LARS,least angle regression),可用作参数选择,得到一个相关系数的稀疏向量 # 产生200个样本,500个特征(维)的回归样本空间 from sklearn.datasets import make_regression reg_data, reg_target = make_regression(n_samples=200, n_features=500, n_informative=5, noise=5) # 线性回归、贝叶斯回归、Lasso回归以及特征提取、岭回归、LARS回归 from sklearn import linear_model regr_model = linear_model.LinearRegression() bys_model = linear_model.BayesianRidge(compute_score=True) lasso_model = linear_model.Lasso() r_model = linear_model.Ridge(alpha=.5) lars_model = linear_model.Lars(n_nonzero_coefs=10) # 交叉验证 lasso_cv = linear_model.LassoCV(alphas=None, copy_X=True, cv=None, eps=0.001, fit_intercept=True, max_iter=1000, n_alphas=100, n_jobs=1, normalize=False, positive=False, precompute='auto', random_state=None, selection='cyclic', tol=0.0001,verbose=False) lasso_cv.fit(reg_data, reg_target) > lasso_cv.alpha_ # 正则化项L1的系数 > lasso_cv.intercept_ # 截距 new_reg_data = reg_data[:,lasso_cv.coef_!=0] #相关系数!=0的特征,被提取得到 # 高斯回归 from sklearn import gaussian_process gp_model = gaussian_process.GaussianProcess(theta0 = 1e-2, thetaL = 1e-4, thetaU= 1e-1) # SVR回归、KR回归 from sklearn.svm import SVR from sklearn.grid_search import GridSearchCV from sklearn.kernel_ridge import KernelRidge svr_model = GridSearchCV(SVR(kernel = 'rbf', gamma = 0.1), cv = 5, param_grid = {"C": [1e0,1e1,1e2,1e3], "gamma": np.logspace(-2, 2, 5)}) kr_model = GridSearchCV(KernelRidge(kernel = 'rbf', gamma = 0.1), cv = 5, param_grid = {"alpha": [1e0,0.1,1e-2,1e-3], "gamma": np.logspace(-2,2,5)}) #训练模型 model.fit (X_train, y_train) # 打印相关系数 print('Coefficients: \n', model.coef_) print("Residual sum of squares: %.2f" % np.mean((model.predict(X_test) - y_test) ** 2)) print('Variance score: %.2f' % model.score(X_test, y_test)) 聚类算法(无监督) K-均值(K-means)聚类,谱聚类,均值偏移,分层聚类,DBSCAN聚类 import numpy as np from sklearn import datasets # 产生500个样本,6个特征(维),5个簇的聚类样本空间 X, Y = datasets.make_blobs(n_samples=500, n_features=6, centers=5, cluster_std=[0.4, 0.3, 0.4, 0.3, 0.4], random_state=11) # K-means Cluster from sklearn.cluster import KMeans clf_model = KMeans(n_clusters=3, max_iter=300, n_init=10) # 谱聚类 from sklearn.cluster import SpectralClustering clf_model = SpectralClustering() #或SpectralClustering(n_clusters=k, gamma=gamma) # DBSCAN Cluster from sklearn.cluster import DBSCAN clf_model = DBSCAN(eps = 0.3, min_samples = 10) #建立模型 clf_model.fit(X) y_pred = clf_model.fit_predict(X) #预测与评价 from sklearn import metrics y_pred = clf_model.labels_ n_clusters_ = len(set(y_pred)) - (1 if -1 in y_pred else 0) print("Estimated number of clusters: %d" % n_clusters_) print("Homogeneity: %0.3f" % metrics.homogeneity_score(Y, y_pred)) print("Completeness: %0.3f" % metrics.completeness_score(Y, y_pred)) print("V-measure: %0.3f" % metrics.v_measure_score(Y, y_pred)) print("Adjusted Rand Index: %0.3f" % metrics.adjusted_rand_score(Y, y_pred)) print("Adjusted Mutual Information: %0.3f" % metrics.adjusted_mutual_info_score(Y, y_pred)) print("Silhouette Coefficient: %0.3f" % metrics.silhouette_score(X, y_pred)) print("Calinski-Harabasz Score", metrics.calinski_harabaz_score(X, y_pred)) 数据降维 目的:减少要考虑的随机变量的个数 应用场景:可视化处理、效率提升 主成分分析(PCA)、非负矩阵分解(NMF)、文档生成主题模型(LDA)、特征选择 # PCA (Principal Components Analysis) from sklearn import decomposition pca = decomposition.PCA() pca.fit(X) # 直接对数据进行降维 print(pca.explained_variance_) pca.n_components = 2 X_reduced = pca.fit_transform(X) # NMF(Nonnegtive Matrix Factorization) from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.decomposition import NMF tfidf_vector = TfidfVectorizer(max_df=0.95, min_df=2, max_features=n_features, stop_words='english') tfidf = tfidf_vector.fit_transform(data_samples) nmf = NMF(n_components=n_topics, random_state=1, alpha=.1, l1_ratio=.5).fit(tfidf) # LDA(Latent Dirichlet Allocation) from sklearn.feature_extraction.text import CountVectorizer from sklearn.decomposition import LatentDirichletAllocation tf_vector = CountVectorizer(max_df=0.95, min_df=2, max_features=n_features, stop_words='english') tf = tf_vector.fit_transform(data_samples) lda = LatentDirichletAllocation(n_topics=n_topics, max_iter=5, learning_method='online', learning_offset=50, random_state=0) .fit(tf) # 打印模型结果 feature_names = vector.get_feature_names() for topic_idx, topic in enumerate(model.components_): print("Topic #%d:" % topic_idx) print(" ".join([feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]])) 模型选择 对于给定参数和模型的比较、验证和选择 目的:通过参数调整来提升精度 格点搜索,交叉验证,各种针对预测误差评估的度量函数 #交叉验证 from sklearn import metrics from sklearn.svm import SVC from sklearn.model_selection import cross_val_score clf = SVC(kernel='linear', C=1) scores = cross_val_score(clf, iris.data, iris.target, cv=5, scoring='f1_macro') print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2)) # 模型的保存与载入 import pickle from sklearn.externals import joblib joblib.dump(clf , 'c:/km.pkl') clf = joblib.load('c:/km.pkl') with open('save/clf.pickle', 'wb') as f: pickle.dump(clf, f) with open('save/clf.pickle', 'rb') as f: clf = pickle.load(f) print(clf.predict(X[0:1])) #测试读取后的Model 11. matplotlib from matplotlib.matlab import * from pylab import * plot(x, y1, 'r*', linewidth=2, label='f(x)=sin(x)') #普通曲线图 plot(x, y2, 'b-', linewidth=2, label='f(x)=2^x') xlabel('x'); ylabel('f(x)'); title('Simple plot') legend(loc='upper left') # 添加图例 grid(True) # 显示网格 savefig("sin.png" ,dpi=72) # 保存图表(dpi为分辨率) show() # 显示图表,注:每次显示后刷新画板 text(2,4, r'αiβjπλωαiβjπλω' , size=15) # text(4,4, r'sin(0)=cost(π2)sin⁡(0)=cost(π2)' , size=15) # text(2,2 , r'limx→y1x3limx→y1x3', size=15) # text(4,2 , r'x√4=y√x4=y', size=15) # 12. jieba https://github.com/fxsjy/jieba import jieba import jieba.posseg as pseg sentence = "我来到北京清华大学" #分词 seg_list = jieba.cut(sentence, cut_all=True) # 全模式 seg_list = jieba.cut(sentence, cut_all=False) # 精确模式 seg_list = jieba.cut(sentence) # 默认是精确模式 seg_list = jieba.cut_for_search(sentence) # 搜索引擎模式 #加载词典,格式:词语 [词频] [词性] jieba.load_userdict(file_name) # file_name 为文件类对象或自定义词典的路径 #手动调整使某个词(不)分开 jieba.suggest_freq(('中', '将'), True) jieba.suggest_freq('台中', True) #关键词提取 jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=('ns', 'n','v')) jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=('ns', 'n','v')) #词性标注 words = pseg.cut(sentence) for word, flag in words: print('%s %s' % (word, flag)) 13. pandas import numpy as np import pandas as pd from pandas import Sereis, DataFrame data = DataFrame(np.arange(16).reshape(4,4),index=list('abcd'),columns=list('wxyz')) a b c d w 0 1 2 3 x 4 5 6 7 y 8 9 10 11 z 12 13 14 15 data[1:4,0:3] #第2到4行,第1到3列 data[['x':'z'],[0:2]] data.iat[1:4,[0:2]] data.ix[1:4,[‘a’,’b’,’c’]] data.loc[['x',’y’,’z’],[‘a’:’c’]] data.irow(0) #第1行 data.iloc[-1:] #最后1行 data.icol(0) #第1列 data.iloc[:-1] #最后1列 data.ix[data.a>5,3] # ‘a’列>5的值所在行【’y’,’z’】,第4列的数据 data.head() #返回data的前几行数据,默认为前五行,需要前十行则data.head(10) data.tail() #返回data的后几行数据,默认为后五行,需要后十行则data.tail(10) 14. nltk l nps_chat # 即时消息聊天会话语料库 l brown # 布朗语料库 [1] 是第一个百万词级的英语电子语料库 [2] 由布朗大学于 1961年创建,包含500个不同来源的文本 [3] 按照文体分类:['adventure', 'belles_lettres', 'editorial', 'fiction', 'government', 'hobbies', 'humor', 'learned', 'lore', 'mystery', 'news', 'religion', 'reviews', 'romance', 'science_fiction'] l reuters # 路透社语料库 [1] 包含 10,788 个新闻文档,共计 130 万字 [2] 这些文档分成 90 个主题,按照“训练”和“测试”分为两组 [3] 新闻报道往往涉及多个主题,类别往往互相重叠 [4] 可以查找由一个或多个文档涵盖的主题,也可以查找包含在一个或多个类别中的文档 l inaugural # 就职演说语料库 [1] 55个文本,每个文本都是一个总统的演说,具有时间维度 l udhr # 标注文本语料库 “世界人权宣言” [1] 包含多国语言['Chickasaw', 'English','German_Deutsch','Greenlandic_Inuktikut','Hungarian_Magyar', 'Ibibio_Efik'] 15. PIL import zbar from PIL import Image #识别二维码 scanner = zbar.ImageScanner() #创建图片扫描对象 scanner.parse_config('enable') #设置对象属性 img = Image.open(filename).convert('L') #打开一张二维码图片, #默认mode="r" qrCode = zbar.Image(img.width, img.height,'Y800', img.tobytes()) #转换图片为字节信息并扫描 scanner.scan(qrCode) data += s.data for s in qrCode del(img) # 删除图片对象 print(data) # 输出解码结果 #在图片上添加文字,增加噪音点 draw = ImageDraw.Draw(img) font = ImageFont.truetype(fontfile, min(img.size)/30) draw.text((0,img.height - fontsize), data, font=font, fill=(255,0,0)) draw.point((random.randint(0,width), random.randint(0,height)), fill=(0,0,255)) #按比例缩放后,模糊处理并保存 rate = max( img.width/p_width, img.height/p_height ) if rate!=0: img.thumbnail((img.size[0]/rate , img.size[1]/rate)) #注:此处有两个括号 img = img.filter(ImageFilter.BLUR) img.show(); img.save(filename, 'jpeg') # 或者是'png' img.close() 16. goose 17. xgboost l 优势 1、 正则化,减少过拟合 2、 并行处理,也支持Hadoop实现 3、 高度的灵活性,允许自定义优化目标和评价标准 4、 缺失值处理 5、 剪枝 6、 内置交叉验证,获得最优boosting迭代次数 7、 可在已有模型上继续训练 l 参数 1、 通用参数:宏观函数控制 u booster:每次迭代的模型,gbtree(默认):基于树的模型,gbliner:线性模型 u silent:0-默认;1-静默模式,不输出任何信息 u nthread:默认值为最大可能的线程数 2、 Booster参数:控制每一步的booster(tree/regression) u eta [默认0.3]:学习速率,通过减少每一步的权重,可提高模型的鲁棒性。 典型值为0.01-0.2。 u min_child_weight [默认1]:最小样本权重的和 u max_depth [默认6]:树的最大深度,典型值:3-10 u max_leaf_nodes:最大的节点或叶子的数量 u gamma [默认0]:节点分裂所需的最小损失函数下降值 u max_delta_step [默认0]:每棵树权重改变的最大步长 u subsample [默认1]:每棵树随机采样的比例,典型值:0.5-1 u colsample_bytree [默认1]:每棵随机采样的列数的占比(每一列是一个特征)。 典型值:0.5-1 u colsample_bylevel [默认1]:树的每一级的每一次分裂,对列数的采样的占比 u lambda [默认1]:权重的L2正则化项,和Ridge regression类似 u alpha [默认1]:权重的L1正则化项,和Lasso regression类似,可以应用在很高维度的情况下,使得算法的速度更快 u scale_pos_weight [默认1]:在样本不平衡时,把这个参数设为一个正值,可以使算法更快收敛 3、 学习目标参数:控制训练目标的表现 u objective [默认reg:linear]:需要被最小化的损失函数。 l binary:logistic 二分类的逻辑回归,返回预测的概率(不是类别) l multi:softmax 使用softmax多分类器,返回预测的类别(不是概率),还需设一个参数:num_class(类别数目) l multi:softprob 和multi:softmax参数一样,但是返回的是每个数据属于各个类别的概率 u eval_metric [默认值取决于objective参数的取值]:对于有效数据的度量方法。 l 对于回归问题,默认值是rmse,均方根误差 l 对于分类问题,默认值是error,二分类错误率(阈值为0.5) l mae 平均绝对误差 l logloss 负对数似然函数值 l merror 多分类错误率 l mlogloss 多分类 l logloss损失函数 l auc 曲线下面积 u seed [默认0]:随机数的种子,设置它可复现随机数据的结果,也可用于调整参数 import xgboost as xgb #加载XGBoost的二进制的缓存文件 dtrain = xgb.DMatrix('train.svm.txt') deval = xgb.DMatrix('test.svm.buffer') #加载Numpy的二维数组,并处理 DMatrix中的缺失值,给样本设置权重 data = np.random.rand(5,10) # 5个训练样本,10个特征 label = np.random.randint(2, size=5) w = np.random.rand(5,1) dtrain = xgb.DMatrix( data, label=label, missing = -999.0, weight=w) #将scipy.sparse格式的数据转化为 DMatrix格式 csr = scipy.sparse.csr_matrix((data, (row,col))) dtrain = xgb.DMatrix(csr) #将DMatrix格式的数据保存成XGBoost的二进制格式,在下次加载时可以提高加载速度 dtrain.save_binary("train.buffer") #参数设置 params = { 'booster': 'gbtree', # gbtree(默认):基于树的模型,gbliner:线性模型 'objective': 'binary:logistic', 'eval_metric':'logloss', 'scale_pos_weight':1, #样本不平衡时,把这个参数设定为正值,可使算法更快收敛 'max_depth':6, #通常取[3,10], 树的最大深度 'min_child_weight':1, #默认为1,最小样本权重的和 'gamma':0.15, #通常取[0.1,0.2],节点分裂所需的最小损失函数下降值,默认为0 'subsample':0.9, #通常取[0.5,1],每棵树随机采样的比例 'colsample_bytree':0.9, #通常取[0.5,0.9],随机采样的列数的占比(每一列是一个特征),默认为1 'lambda':0.1, #权重的L2正则化项 'alpha':0.2, #权重的L1正则化项 'eta':0.15 #学习速率,默认为0.3,通常取[0.01,0.2] } plst = param.items() #调整参数 res = xgb.cv(params, xgTrain) #定义验证数据集,验证算法的性能 evallist = [(deval,'eval'), (dtrain,'train')] #训练模型 num_round = 10 bst = xgb.train( plst, dtrain, num_round, evallist, evals=evals, early_stopping_rounds=5) #保存模型 bst.save_model('model.bin') bst.dump_model('dump.raw.txt') bst.dump_model('dump.raw.txt','featmap.txt') #加载模型 bst = xgb.Booster({'nthread':4}) model = bst.load_model("model.bin") #预测结果 data = np.random.rand(7,10) # 7个测试样本,10个特征 dtest = xgb.DMatrix(data, missing = -999.0 ) ypred = bst.predict(model) ypred = bst.predict(model, ntree_limit=bst.best_iteration) 转自:https://www.cnblogs.com/sweetyu/p/6863560.html

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

Java锁细节整理

一、JDK8存在的锁 synchronized StampedLock ReentrantLock ReentrantReadWriteLock PS: 下面内容测试的结果不是十分正确。第一,测试的jdk是1.6,而不是1.8.测试的没有关闭UseBiasedLocking(偏向锁) 二、锁的特性 1 锁升级(十二分) 多种强度的锁方式。优先使用性能消耗低的方式,当当前方式不可用或者不使用,改变成消耗比当前大的锁方式。 是一种十分灵活,智能的性能优化方案,对非特定场景十分适合。不需要开发者关注锁优化,只需要关注业务。 2 重入(十二分) 同一个锁, 重入是应付锁复杂使用情况下的一把利器,是锁性能重点。a与b方式使用同一个锁。a调用b,需要两个锁指令,而重入的解决方案是a执行锁指令,当a调用b方法的时候,不使用锁指令。那么锁的开销减少一半。重入得越多锁开销减少越多。 有测试哪里,需要大家自己测试。 下面的链接中性能测试其实已经给了答案,不知道哪位大神,可以把答案告诉打杂的老胡 3 读写(六分) 分读写锁,读锁与读锁之间可以共享。在读多写少的场景,提高锁的性能 下面博客有对读写的性能测试:http://www.inter12.org/archives/292 4 公平 为了性能,不按上锁的循序获得锁,即不公平锁。按照上锁的循序获得锁,即公平锁。 公平不是为了优先级 下面博客有对公平的性能测试:https://yq.aliyun.com/articles/48612 5 自动释放(十二分) 不用手动调用unLock系列释放锁的方法。解决在复杂的开发体系(业务复杂,开发人员能力参差不齐,细节无视与混淆,测试困难)中,锁操作问题。 异常释放,谁来释放。 6. 锁等待(六分) 当其他线程获得锁之后,等待固定时间之后,还没有获得锁就不在争夺锁。 线程中断(一分) 三、开发难度 特性支持 开发人员使用分类 锁应用环境 业务模块基本不需要关注锁,需要锁的地方都应该使用synchronized,高级以下程序员都使用的数据库锁,或者其他库锁。打杂的目前在业务系没有用过java锁, 功能模块的开发与维护基本是高级或者研发人员,用到锁的地方不多,绝对大部分是使用的 synchronized 与 ReentrantLock ,在 spring 的代码里面只见到许多 synchronized,ReentrantLock 还没见过 软件系比如 netty,dubbo ,大量使用 ReentrantLock ,一些独立的服务比如 rocketmq ,核心业务重写了 ReentrantLock ,还有设计自己的加锁机制 读写类型 业务模块基本不需要关注锁,需要锁的地方都应该使用synchronized,高级以下程序员都使用的数据库锁,或者其他库锁。打杂的目前在业务系没有用过java锁, 功能模块的开发与维护基本是高级或者研发人员,用到锁的地方不多,绝对大部分是使用的synchronized与ReentrantLock,在spring的代码里面只见到许多synchronized,ReentrantLock还没见过 软件系比如netty,dubbo,大量使用ReentrantLock,一些独立的服务比如rocketmq,核心业务重写了ReentrantLock,还有设计自己的加锁机制 全写操作目前发现最多的就是计数器,计数器建议使用jdk8的LongAdders(计数器),性能超级好。注意任何计数器无法保证绝对的精确性。 ReentrantLock与ReentrantReadWriteLock的写性能一样。 总结 如果要对特性重要进行排序,要排除对性能极限要求的情况,可以得到以下结论: 重入>锁升级>自动释放>锁等待超时>公平>读写>线程中断 在繁多,复杂的方法,代码,逻辑之间相互调用。谁也不知道,哪个方法,哪段代码使用了锁,一不小心死锁。所以重入是最重要的一点。 除非资深研发人员否则其他人员不应该使用StampedLock 锁升级可以做基本性能方面优化,就交给锁了,可以让锁性能在个个场景都可以保持较好的状态,从而减少锁开发与维护的工作量 自动释放对初级,中级或者高级开发来说,是一个避免出现锁问题的利器,保障开发简单,顺利。不用担心哪里忘记释放锁,从而造成锁问题 锁等待超时是防止无限锁等待而造成线程资源无限占用与线程池无线程可用的情况,从而让应用无法提供服务。是高可用服务保障的利器 复杂的环境下,不知道哪个方法,哪个代码使用了读锁还是写锁。太多未知与细节,十分头疼,需要大量的时间与精力处理读写关系,得不偿失。 做了这么多年开发与研发。感觉性能较好的情况下,不出问题与开发维护方便应该放在对性能高度最求的前面。尤其是线上问题,应该避免出现。 从上面的对比分析,synchronized的得分与评价是最高的,ReentrantLock其次, 不建议使用ReentrantReadWriteLock,禁止使用StampedLock。 四、synchronized详析 synchronized 是java关键字,jvm内部实现。所以jvm可以对synchronized进行优化 每个jdk版本synchronized性能不一样,版本越高的性能越好。jdk1.6与jdk1.7之间的性能差距十分大。 synchronized操作简单,jvm自动优化性能 synchronized详析锁的方式 public class SynchronizedLockMode { private static int increment = 0; private Object object = new Object( ); public synchronized void lockMethod(){ print("lockMethod"); } public synchronized static void lockStaticMethod(){ print("lockStaticMethod"); } public void lockBlock(){ synchronized( object ){ print("lockBlock"); } } } 运行代码: @Test public void synchronizedLockModeTest(){ SynchronizedLockMode slm = new SynchronizedLockMode(); Thread thread1 = new Thread( new Runnable( ) { public void run ( ) { slm.lockMethod( ); } } ); Thread thread2 = new Thread( new Runnable( ) { public void run ( ) { SynchronizedLockMode.lockStaticMethod( ); } } ); Thread thread3 = new Thread( new Runnable( ) { public void run ( ) { slm.lockBlock( ); } } ); thread1.start( ); thread2.start( ); thread3.start( ); try { Thread.sleep( 1000 ); } catch ( InterruptedException e ) { e.printStackTrace(); } } 运行结果: lockMethod: 0 for num0 lockBlock: 1 for num0 lockStaticMethod: 0 for num0 lockBlock: 3 for num1 lockMethod: 2 for num1 lockBlock: 5 for num2 lockStaticMethod: 4 for num1 lockBlock: 7 for num3 lockMethod: 6 for num2 lockBlock: 9 for num4 lockStaticMethod: 8 for num2 lockBlock: 11 for num5 lockMethod: 10 for num3 lockBlock: 13 for num6 lockStaticMethod: 12 for num3 lockBlock: 15 for num7 lockBlock: 17 for num8 lockMethod: 14 for num4 lockBlock: 18 for num9 lockBlock: 20 for num10 lockBlock: 21 for num11 lockStaticMethod: 16 for num4 lockBlock: 22 for num12 lockMethod: 19 for num5 lockBlock: 24 for num13 lockStaticMethod: 23 for num5 lockBlock: 26 for num14 lockMethod: 25 for num6 lockBlock: 28 for num15 lockStaticMethod: 27 for num6 lockBlock: 30 for num16 lockMethod: 29 for num7 lockBlock: 32 for num17 lockStaticMethod: 31 for num7 lockBlock: 34 for num18 lockMethod: 33 for num8 lockBlock: 36 for num19 lockStaticMethod: 35 for num8 lockStaticMethod: 38 for num9 lockStaticMethod: 39 for num10 lockStaticMethod: 40 for num11 lockStaticMethod: 41 for num12 lockStaticMethod: 42 for num13 lockMethod: 37 for num9 lockStaticMethod: 43 for num14 lockMethod: 44 for num10 lockStaticMethod: 45 for num15 lockMethod: 46 for num11 lockStaticMethod: 47 for num16 lockMethod: 48 for num12 lockStaticMethod: 49 for num17 lockMethod: 50 for num13 lockStaticMethod: 51 for num18 lockMethod: 52 for num14 lockStaticMethod: 53 for num19 lockMethod: 54 for num15 lockMethod: 55 for num16 lockMethod: 56 for num17 lockMethod: 57 for num18 lockMethod: 58 for num19 从上面的执行可以是否发现一个问题,答应是乱序的,自增数据是乱序的。 很多人认为:绝对是java设计的失误...使用一个图片来逻辑推理下: java与jvm绝对没有错 synchronized是上锁,这点绝对没有问题 那synchronized锁了什么了? 这是我们讨论的论题,也是一个容易犯错的问题。 演示代码,有四个方法。 public synchronized void lockThisObject(){ sleep("synchronized method"); } public void VerificationLockMethodIsWhatObject(){ synchronized( this ){ sleep("synchronized block lock this" , false); } } public synchronized static void lockClassObject(){ sleep("synchronized method static "); } public void VerificationLockStaticMethodIsWhatObject(){ synchronized( SynchronizedLockMode.class ){ sleep("synchronized block lock SynchronizedLockMode.class" , false); } } private static void sleep(String lock , boolean boo){ if(boo){ sleep( lock ); }else{ System.out.println( lock + " execute" ) ; } } private static void sleep(String lock){ sleep0( lock ); } private static void sleep0(String lock){ try { System.out.println( lock + " start sleep" ) ; Thread.sleep( 10000 ); System.out.println( lock + " end sleep" ) ; } catch ( InterruptedException e ) { e.printStackTrace(); } } 代码解读 有四个方法分别是静态方法,非静态方法,两个方法里面有synchronized block。四个方法分别组合,测试方法的互斥行。输出内容是按照调用方法的循序执行的,synchronized block方法的输出结果在synchronized 方法之后,那么表示两个方法是互斥的。组合: 锁静态方法 块锁锁住this; 锁静态方法 块锁锁住Class; 锁非静态方法 块锁锁住this ; 锁非静态方法 块锁锁住Class。 test代码与结果 第一个组合 SynchronizedLockMode slm = new SynchronizedLockMode(); Thread thread1 = new Thread( new Runnable( ) { public void run ( ) { SynchronizedLockMode.lockClassObject( ); } } ); Thread thread2 = new Thread( new Runnable( ) { public void run ( ) { slm.verificationLockMethodIsWhatObject( ); } } ); System.out.println( "第一个组合 锁静态方法 块锁锁住this" ) ; thread1.start( ); sleep(); thread2.start( ); sleep(10000); System.out.println( "第一个组合 执行结束" ) ; 第一个组合 锁静态方法 块锁锁住thissynchronized method static start sleepsynchronized block lock this executesynchronized method static end sleep 第一个组合 执行结束 第二个组合: thread1 = new Thread( new Runnable( ) { public void run ( ) { SynchronizedLockMode.lockClassObject( ); } } ); thread2 = new Thread( new Runnable( ) { public void run ( ) { slm.verificationLockStaticMethodIsWhatObject( ); } } ); System.out.println( "第二个组合 锁静态方法 块锁锁住Class" ) ; thread1.start( ); sleep(); thread2.start( ); sleep(10000); System.out.println( "第二个组合 执行结束" ) ; 第二个组合 锁静态方法 块锁锁住Classsynchronized method static start sleepsynchronized method static end sleepsynchronized block lock SynchronizedLockMode.class execute 第二个组合 执行结束 第三个组合: thread1 = new Thread( new Runnable( ) { public void run ( ) { slm.lockThisObject( ); } } ); thread2 = new Thread( new Runnable( ) { public void run ( ) { slm.verificationLockMethodIsWhatObject( ); } } ); System.out.println( "第三个组合 锁非静态方法 块锁锁住this" ) ; thread1.start( ); sleep(); thread2.start( ); sleep(10000); System.out.println( "第三个组合 执行结束" ) ; 第三个组合 锁非静态方法 块锁锁住thissynchronized method start sleepsynchronized method end sleepsynchronized block lock this execute 第三个组合 执行结束 第四个组合 thread1 = new Thread( new Runnable( ) { public void run ( ) { slm.lockThisObject( ); } } ); thread2 = new Thread( new Runnable( ) { public void run ( ) { slm.verificationLockStaticMethodIsWhatObject( ); } } ); System.out.println( "第四个组合 非锁静态方法 块锁锁住Class" ) ; thread1.start( ); sleep(); thread2.start( ); sleep(10000); System.out.println( "第四个组合 执行结束" ) ; 第四个组合 非锁静态方法 块锁锁住Classsynchronized method start sleepsynchronized block lock SynchronizedLockMode.class executesynchronized method end sleep 第四个组合 执行结束 通过结果分析会发现第二,三组合的输出结果是有序的。麻烦在看看二,三组合调用的方法 第二个组合是: 锁静态方法 块锁锁住Class 第三个组合是: 锁非静态方法 块锁锁住this 结论: synchronized关键字标记在静态方法上是锁当前的class对象。 public synchronized static void XXXXX(){ // 锁的对象是 当前的 class } synchronized关键字标记在非静态方法上是锁当前的实例对象(this) public synchronized void XXXXX(){ // 锁的对象是 当前的 this } 总结 jdk版本越高synchronized的性能越好 这是阿里大神fashjson与driud的作者温 对synchronized简单总结 背景: 某日,对某个优化过的系统进行,上线前的性能压测,压测结果大大的出乎人意料,优化之后比优化之前的TPS只多200+。在16cpu的服务器不应该出现这样的情况。 问题排查: 是不是接口中数据库操作的问题,MySQL通用日志里记录的sql基本一致,慢日志里面没有记录接口操作的sql。是不是测试人员的测试数据十分重复,更新操作造成锁超时,准备排除锁超时情况,测试人员与业务开发人员反馈,查询接口也一样,数据状态良好 是不是代码问题,分析最后的此时结果,发现所有压测接口都这样。包括简单条主键查询的SQL Why? 奇迹了,数据库与应用一切正常啊。被逼无赖,在每个核心地方输出调用时间,也没问题。发现所有的接口的使用了RateLimiter的acquire方法,深入一看,有synchronized。每次接口的调用都会进入下面的代码,而每次都会有锁争夺。 解决方案: 高并发下synchronize造成jvm性能消耗详析 jvm对synchronized代码块的优化 google guava 的RateLimiter 限流的核心计算代码使用的synchronized,google大神都证明了synchronized的优秀 公平锁与不公平锁: 在一般竞争情况下,两者的性能可以理解为相等 在极高竞争下,不公平锁的性能是可能是公平锁的十几倍 ReentrantReadWriteLock 死锁现象 背景 某个深夜,老胡在看ReentrantReadWriteLock源码,想用ReentrantReadWriteLock代替ReentrantLock提高性能,反复的看调用流程与实现细节(看了两个多小时), 脑海慢慢呈现整个调用流程与实现细节的流程与逻辑图,发现不对劲啊,可能一不小心出现死锁 public void reentrantReadWriteLock() throws InterruptedException{ ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock(); ReadLock readLock = rrwl.readLock( ); WriteLock wrtieLock = rrwl.writeLock( ); readLock.lock( ); readLock.lock( ); readLock.unlock( ); readLock.unlock( ); wrtieLock.lock( ); wrtieLock.lock( ); wrtieLock.unlock( ); wrtieLock.unlock( ); wrtieLock.lock( ); readLock.lock( ); wrtieLock.unlock( ); readLock.unlock( ); readLock.lock( ); wrtieLock.lockInterruptibly( ); readLock.unlock( ); wrtieLock.unlock( ); } 经过测试之后,老胡出了一点冷汗,这个死锁隐藏得太深了。还好是老胡慢慢,慢,看出来了,以老胡的编码方式,还真得出现这样的死锁 ReentrantLock 与 ReentrantReadWriteLock 在高并发下的不公平锁 出现饿死现象: 在发现死锁现象同一个深夜,老胡在仔细反复的看公布与不公平,读写锁的细节。反复的看调用流程与实现细节,一边准备与周公喝茶了,一个低头砸到桌子上,脑海里整个调用流程与实现细节的流程与逻辑图砸出一个闪光,找到一个问题 在高并发下,很多线程争夺一个锁的时候,在队列的里面的锁可能能难争夺到锁,争夺不到,会饿死啊。 锁使用总结:在高并发情况下,使用tryLock(超时)杜绝 饥饿。没获得锁,可以直接异常与返回异常结果 能不使用锁,绝对不要使用........... 注意上面说的细节,比如synchronized锁的对象等 优先使用synchronized关键字,能不用使用synchronized块就不使用 高并发的情况下使用synchronized,麻烦关闭偏向锁-XX:-UseBiasedLocking 减少锁粒度 优先使用重入锁,禁止非重入锁StampedLock的使用 一定要分析场景,在选择对应的锁,如果不分析只能使用synchronized tryLock(超时) 是处理死锁与饥饿的神器。 一个class或者一个实例里面只允许一个锁。两个锁容易出现死锁。这个锁必须能重入 private Object object = new Object(); public void a(){ synchronized(object){ } } public void b(){ synchronized(object){ } } // c 方法与a,b方法的锁不是一个,在这个类里面有两个锁分别是 object与this, public void c(){ synchronized(this){ } } // 同时存在 a b锁,很容易不小心死锁。 ReentrantLock a= new ReentrantLock(); ReentrantLock b= new ReentrantLock(); 原文发布时间为:2018-02-2 本文作者:鸟菜啊 本文来自云栖社区合作伙伴“ 老叶茶馆”,了解相关信息可以关注“ 老叶茶馆”微信公众号

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

Android的Layout整理

1.FrameLayout FrameLayout 是 最简单的一个布局对象。它被定制为你屏幕上的一个空白备用区域,之后你可以在其中填充一个单一对象 — 比如,一张你要发布的图片。所有的子元素将会固定 在屏幕的左上角;你不能为FrameLayout中的一个子元素指定一个位置。后一个子元素将会直接在前一个子元素之上进行覆盖填充,把它们部份或全部挡 住(除非后一个子元素是透明的)。 FrameLayout is the simplest type of layout object. It's basically a blank space on your screen that you can later fill with a single object — for example, a picture that you'll swap in and out. All child elements of the FrameLayout are pinned to the top left corner of the screen; you cannot specify a different location for a child view. Subsequent child views will simply be drawn over previous ones, partially or totally obscuring them (unless the newer object is transparent). FrameLayout默认填充widget等在左上角,然后后面的控件遮住前面的,比如说有两个TextView,Text内容分别是I am textview 1 和 I am textview 2 看到的效果会如下: ?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="htHTMLtp://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 1" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 2" /> </FrameLayout> 2. LinearLayout LinearLayout 以你为它设置的垂直或水平的属性值,来排列所有的子元素。所有的子元素都被堆放在其它元素之后,因此一个垂直列表的每一行只会有一个元素,而不管他们有多 宽,而一个水平列表将会只有一个行高(高度为最高子元素的高度加上边框高度)。LinearLayout保持子元素之间的间隔以及互相对齐(相对一个元素 的右对齐、中间对齐或者左对齐)。 LinearLayout 还支持为单独的子元素指定weight。好处就是允许子元素可以填充屏幕上的剩余空间。这也避免了在一个大屏幕中,一串小对象挤成一堆的情况,而是允许他们放大填充空白。子元素指定一个weight值,剩余的空间就会按这些子元素指定的weight比例分配给这些子元素。默认的weight值为0。例如,如 果有三个文本框,其中两个指定了weight值为1,那么,这两个文本框将等比例地放大,并填满剩余的空间,而第三个文本框不会放大。 下 面的两个窗体采用LinearLayout,包含一组的元素:一个按钮,几个标签,几个文本框。两个窗体都为布局做了一番修饰。文本框的width被设置 为FILL_PARENT;其它元素的width被设置为WRAP_CONTENT。默认的对齐方式为左对齐。左边的窗体没有设置weight(默认为 0);右边的窗体的comments文本框weight被设置为1。如果Name文本框也被设置为1,那么Name和Comments这两个文本框将会有同样的高度。 在 一个水平排列的LinearLayout中,各项按他们的文本基线进行排列(第一列第一行的元素,即最上或最左,被设定为参考基线)。因此,人们在一个窗 体中检索元素时,就不需要七上八下地读元素的文本了。我们可以在layout的XML中设置 android:baselineAligned="false",来关闭这个设置。 LinearLayoutaligns all children in a single direction — vertically or horizontally, depending on how you define the orientationattribute. All children are stacked one after the other, so a vertical list will only have one child per row, no matter how wide they are, and a horizontal list will only be one row high (the height of the tallest child, plus padding). A LinearLayoutrespects margins between children and the gravity(right, center, or left alignment) of each child. LinearLayout是Android sdk创建project时的默认Layout,支持两种方式,默认是垂直vertical的线性layout,另一个是水平horizontal方向的线性排列。 效果如下 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 1" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 2" /> </LinearLayout> <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="10px" android:layout_height="fill_parent" android:text="I am textview 1" /> <TextView android:layout_width="10px" android:layout_height="wrap_content" android:text="I am textview 2" /> </LinearLayout> 3. RelativeLayout RelativeLayout 允 许子元素指定他们相对于其它元素或父元素的位置(通过ID指定)。因此,你可以以右对齐,或上下,或置于屏幕中央的形式来排列两个元素。元素按顺序排列, 因此如果第一个元素在屏幕的中央,那么相对于这个元素的其它元素将以屏幕中央的相对位置来排列。如果使用XML来指定这个layout,在你定义它之前, 被关联的元素必须定义。 这是一个RelativeLayout例子,其中有可视的和不可视的元素。基础的屏幕layout对象是一个RelativeLayout对象。 这 个视图显示了屏幕元素的类名称,下面是每个元素的属性列表。这些属性一部份是由元素直接提供,另一部份是由容器的LayoutParams成员 (RelativeLayout的子类)提供。RelativeLayout参数有 width,height,below,alignTop,toLeft,padding和marginLeft。注意,这些参数中的一部份,其值是相对 于其它子元素而言的,所以才RelativeLayout。这些参数包括toLeft,alignTop和below,用来指定相对于其它元素的左,上和 下的位置。 RelativeLayoutlets child views specify their position relative to the parent view or to each other (specified by ID). So you can align two elements by right border, or make one below another, centered in the screen, centered left, and so on. Elements are rendered in the order given, so if the first element is centered in the screen, other elements aligning themselves to that element will be aligned relative to screen center. Also, because of this ordering, if using XML to specify this layout, the element that you will reference (in order to position other view objects) must be listed in the XML file before you refer to it from the other views via its reference ID. <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding = "10px" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 1" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 2" android:layout_marginLeft = "150px" /> <Button android:id="@+id/Button02" android:layout_width="wrap_content" android:text="Ok" android:layout_height="wrap_content" android:layout_marginLeft = "240px" android:layout_marginTop = "40px" ></Button> <Button android:id="@+id/Button01" android:layout_width="wrap_content" android:text="Cancel" android:layout_height="wrap_content" android:layout_marginLeft = "160px" android:layout_marginTop = "40px" ></Button> </RelativeLayout 4.AbsoluteLayout 可 以让子元素指定准确的x/y坐标值,并显示在屏幕上。(0, 0)为左上角,当向下或向右移动时,坐标值将变大。AbsoluteLayout没有页边 框,允许元素之间互相重叠(尽管不推荐)。我们通常不推荐使用AbsoluteLayout,除非你有正当理由要使用它,因为它使界面代码太过刚性,以至 于在不同的设备上可能不能很好地工作。 5.TableLayout TableLayout 将子元素的位置分配到行或列中。android的 一个TableLayout由许多的TableRow组成,每个TableRow都会定义一个row(事实上,你可以定义其它的子对象,这在下面会解释 到)。TableLayout容器不会显示row、cloumns或cell的边框线。每个row拥有0个或多个的cell;每个cell拥有一个 View对象。表格由列和行组成许多的单元格。表格允许单元格为空。单元格不能跨列,这与HTML中的不一样。下图显示了一个TableLayout,图 中的虚线代表不可视的单元格边框。 列可以被隐藏,也可以被设置为伸展的从而填充可利用的屏幕空间,也可以被设置为强制列收缩直到表格匹配屏幕大小。对于更详细信息,可以查看这个类的参考文档。 TableLayoutpositions its children into rows and columns. TableLayout containers do not display border lines for their rows, columns, or cells. The table will have as many columns as the row with the most cells. A table can leave cells empty, but cells cannot span columns, as they can in HTML. TableRowobjects are the child views of a TableLayout (each TableRow defines a single row in the table). Each row has zero or more cells, each of which is defined by any kind of other View. So, the cells of a row may be composed of a variety of View objects, like ImageView or TextView objects. A cell may also be a ViewGroup object (for example, you can nest another TableLayout as a cell). TableLayout和HTML的<table>基本上类似,还提供TableRow class, 直接等价与<tr> 比如说要做成一个类似下面的HTML叶面 I am textview1 I am textview2 [OK button] [Cancel button] <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TableRow android:background="@drawable/a1"> <TextView android:text="I am textview 1" /> <TextView android:paddingLeft = "20px" android:width = "200px" android:text="I am textview 2" /> </TableRow> <TableRow android:background="@drawable/a1"> <Button android:id="@+id/Button02" android:text="Ok" ></Button> <Button android:id="@+id/Button01" android:text="Cancel" ></Button> </TableRow> </TableLayout> 1.FrameLayout FrameLayout 是 最简单的一个布局对象。它被定制为你屏幕上的一个空白备用区域,之后你可以在其中填充一个单一对象 — 比如,一张你要发布的图片。所有的子元素将会固定 在屏幕的左上角;你不能为FrameLayout中的一个子元素指定一个位置。后一个子元素将会直接在前一个子元素之上进行覆盖填充,把它们部份或全部挡 住(除非后一个子元素是透明的)。 FrameLayout is the simplest type of layout object. It's basically a blank space on your screen that you can later fill with a single object — for example, a picture that you'll swap in and out. All child elements of the FrameLayout are pinned to the top left corner of the screen; you cannot specify a different location for a child view. Subsequent child views will simply be drawn over previous ones, partially or totally obscuring them (unless the newer object is transparent). FrameLayout默认填充widget等在左上角,然后后面的控件遮住前面的,比如说有两个TextView,Text内容分别是I am textview 1 和 I am textview 2 看到的效果会如下: ?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="htHTMLtp://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 1" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 2" /> </FrameLayout> 2. LinearLayout LinearLayout 以你为它设置的垂直或水平的属性值,来排列所有的子元素。所有的子元素都被堆放在其它元素之后,因此一个垂直列表的每一行只会有一个元素,而不管他们有多 宽,而一个水平列表将会只有一个行高(高度为最高子元素的高度加上边框高度)。LinearLayout保持子元素之间的间隔以及互相对齐(相对一个元素 的右对齐、中间对齐或者左对齐)。 LinearLayout 还支持为单独的子元素指定weight。好处就是允许子元素可以填充屏幕上的剩余空间。这也避免了在一个大屏幕中,一串小对象挤成一堆的情况,而是允许他们放大填充空白。子元素指定一个weight值,剩余的空间就会按这些子元素指定的weight比例分配给这些子元素。默认的weight值为0。例如,如 果有三个文本框,其中两个指定了weight值为1,那么,这两个文本框将等比例地放大,并填满剩余的空间,而第三个文本框不会放大。 下 面的两个窗体采用LinearLayout,包含一组的元素:一个按钮,几个标签,几个文本框。两个窗体都为布局做了一番修饰。文本框的width被设置 为FILL_PARENT;其它元素的width被设置为WRAP_CONTENT。默认的对齐方式为左对齐。左边的窗体没有设置weight(默认为 0);右边的窗体的comments文本框weight被设置为1。如果Name文本框也被设置为1,那么Name和Comments这两个文本框将会有同样的高度。 在 一个水平排列的LinearLayout中,各项按他们的文本基线进行排列(第一列第一行的元素,即最上或最左,被设定为参考基线)。因此,人们在一个窗 体中检索元素时,就不需要七上八下地读元素的文本了。我们可以在layout的XML中设置 android:baselineAligned="false",来关闭这个设置。 LinearLayoutaligns all children in a single direction — vertically or horizontally, depending on how you define the orientationattribute. All children are stacked one after the other, so a vertical list will only have one child per row, no matter how wide they are, and a horizontal list will only be one row high (the height of the tallest child, plus padding). A LinearLayoutrespects margins between children and the gravity(right, center, or left alignment) of each child. LinearLayout是Android sdk创建project时的默认Layout,支持两种方式,默认是垂直vertical的线性layout,另一个是水平horizontal方向的线性排列。 效果如下 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 1" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 2" /> </LinearLayout> <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="10px" android:layout_height="fill_parent" android:text="I am textview 1" /> <TextView android:layout_width="10px" android:layout_height="wrap_content" android:text="I am textview 2" /> </LinearLayout> 3. RelativeLayout RelativeLayout 允 许子元素指定他们相对于其它元素或父元素的位置(通过ID指定)。因此,你可以以右对齐,或上下,或置于屏幕中央的形式来排列两个元素。元素按顺序排列, 因此如果第一个元素在屏幕的中央,那么相对于这个元素的其它元素将以屏幕中央的相对位置来排列。如果使用XML来指定这个layout,在你定义它之前, 被关联的元素必须定义。 这是一个RelativeLayout例子,其中有可视的和不可视的元素。基础的屏幕layout对象是一个RelativeLayout对象。 这 个视图显示了屏幕元素的类名称,下面是每个元素的属性列表。这些属性一部份是由元素直接提供,另一部份是由容器的LayoutParams成员 (RelativeLayout的子类)提供。RelativeLayout参数有 width,height,below,alignTop,toLeft,padding和marginLeft。注意,这些参数中的一部份,其值是相对 于其它子元素而言的,所以才RelativeLayout。这些参数包括toLeft,alignTop和below,用来指定相对于其它元素的左,上和 下的位置。 RelativeLayoutlets child views specify their position relative to the parent view or to each other (specified by ID). So you can align two elements by right border, or make one below another, centered in the screen, centered left, and so on. Elements are rendered in the order given, so if the first element is centered in the screen, other elements aligning themselves to that element will be aligned relative to screen center. Also, because of this ordering, if using XML to specify this layout, the element that you will reference (in order to position other view objects) must be listed in the XML file before you refer to it from the other views via its reference ID. <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding = "10px" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 1" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="I am textview 2" android:layout_marginLeft = "150px" /> <Button android:id="@+id/Button02" android:layout_width="wrap_content" android:text="Ok" android:layout_height="wrap_content" android:layout_marginLeft = "240px" android:layout_marginTop = "40px" ></Button> <Button android:id="@+id/Button01" android:layout_width="wrap_content" android:text="Cancel" android:layout_height="wrap_content" android:layout_marginLeft = "160px" android:layout_marginTop = "40px" ></Button> </RelativeLayout 4.AbsoluteLayout 可 以让子元素指定准确的x/y坐标值,并显示在屏幕上。(0, 0)为左上角,当向下或向右移动时,坐标值将变大。AbsoluteLayout没有页边 框,允许元素之间互相重叠(尽管不推荐)。我们通常不推荐使用AbsoluteLayout,除非你有正当理由要使用它,因为它使界面代码太过刚性,以至 于在不同的设备上可能不能很好地工作。 5.TableLayout TableLayout 将子元素的位置分配到行或列中。android的 一个TableLayout由许多的TableRow组成,每个TableRow都会定义一个row(事实上,你可以定义其它的子对象,这在下面会解释 到)。TableLayout容器不会显示row、cloumns或cell的边框线。每个row拥有0个或多个的cell;每个cell拥有一个 View对象。表格由列和行组成许多的单元格。表格允许单元格为空。单元格不能跨列,这与HTML中的不一样。下图显示了一个TableLayout,图 中的虚线代表不可视的单元格边框。 列可以被隐藏,也可以被设置为伸展的从而填充可利用的屏幕空间,也可以被设置为强制列收缩直到表格匹配屏幕大小。对于更详细信息,可以查看这个类的参考文档。 TableLayoutpositions its children into rows and columns. TableLayout containers do not display border lines for their rows, columns, or cells. The table will have as many columns as the row with the most cells. A table can leave cells empty, but cells cannot span columns, as they can in HTML. TableRowobjects are the child views of a TableLayout (each TableRow defines a single row in the table). Each row has zero or more cells, each of which is defined by any kind of other View. So, the cells of a row may be composed of a variety of View objects, like ImageView or TextView objects. A cell may also be a ViewGroup object (for example, you can nest another TableLayout as a cell). TableLayout和HTML的<table>基本上类似,还提供TableRow class, 直接等价与<tr> 比如说要做成一个类似下面的HTML叶面 I am textview1 I am textview2 [OK button] [Cancel button] <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TableRow android:background="@drawable/a1"> <TextView android:text="I am textview 1" /> <TextView android:paddingLeft = "20px" android:width = "200px" android:text="I am textview 2" /> </TableRow> <TableRow android:background="@drawable/a1"> <Button android:id="@+id/Button02" android:text="Ok" ></Button> <Button android:id="@+id/Button01" android:text="Cancel" ></Button> </TableRow> </TableLayout> 本文转自xyz_lmn51CTO博客,原文链接:http://blog.51cto.com/xyzlmn/819191,如需转载请自行联系原作者

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

整理)elasticsearch相关概念

参考网址 elasticsearch权威指南:https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html elasticsearch-sql:https://github.com/NLPchina/elasticsearch-sql ElasticSearch查询:http://www.cnblogs.com/ljhdo/p/4551490.html ElasticSearch multifields说明:https://stackoverflow.com/questions/40271980/elasticsearch-multi-field-with-raw-value-not-being-created 23种非常有用的ElasticSearch查询例子:https://www.iteblog.com/archives/1741.html 推荐书籍 Elasticsearch服务器开发:https://item.jd.com/11615450.html 数据同步插件 待补充 index和type的概念 http://www.bayescafe.com/database/elasticsearch-using-index-or-type.html mapping概念介绍 https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html ES和mysql概念对比 一个ES集群可以包含多个索引(数据库),每个索引又包含了很多类型(表),类型中包含了很多文档(行),每个文档又包含了很多字段(列)。 传统数据库为特定列增加一个索引,例如B-Tree索引来加速检索。Elasticsearch和Lucene使用一种叫做倒排索引(inverted index)的数据结构来达到相同目的。 倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。 关于全文查询和词条查询的说明 尽管所有的查询都会执行某种程度的相关度计算,并不是所有的查询都存在解析阶段。除了诸如bool或者function_score这类完全不对文本进行操作的特殊查询外,对于文本的查询可以被划分两个种类: 基于词条的查询(Term-based Queries) 类似term和fuzzy的查询是不含有解析阶段的低级查询(Low-level Queries)。它们在单一词条上进行操作。一个针对词条Foo的term查询会在倒排索引中寻找该词条的精确匹配(Exact term),然后对每一份含有该词条的文档通过TF/IDF进行相关度_score的计算。 尤其需要记住的是term查询只会在倒排索引中寻找该词条的精确匹配 - 它不会匹配诸如foo或者FOO这样的变体。它不在意词条是如何被保存到索引中。如果你索引了["Foo", "Bar"]到一个not_analyzed字段中,或者将Foo Bar索引到一个使用whitespace解析器的解析字段(Analyzed Field)中,它们都会在倒排索引中得到两个词条:"Foo"以及"Bar"。 全文查询(Full-text Queries) 类似match或者query_string这样的查询是高级查询(High-level Queries),它们能够理解一个字段的映射: 如果你使用它们去查询一个date或者integer字段,它们会将查询字符串分别当做日期或者整型数。 如果你查询一个精确值(not_analyzed)字符串字段,它们会将整个查询字符串当做一个单独的词条。 但是如果你查询了一个全文字段(analyzed),它们会首先将查询字符串传入到合适的解析器,用来得到需要查询的词条列表。 一旦查询得到了一个词条列表,它就会使用列表中的每个词条来执行合适的低级查询,然后将得到的结果进行合并,最终产生每份文档的相关度分值。

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

MaxCompute应用限制整理

好多同学在使用MaxCompute时,对产品的应用限制并不了解。这里,我们将给出MaxCompute产品的详细应用限制列表。如有遗漏,还请大家补充: 命名规范:原则上,项目(Project),表(Table),函数(Function),资源(Resource),分区(Partition),列的名称都不能有特殊字符,只能用英文的a-z,A-Z及数字和下划线_,且以字母开头,名称的长度不超过128字节。实际情况可能会略有不同,但我们仍然建议您遵循这个原则进行命名。 Task并发度控制:通常情况下,MaxCompute会在项目级别做Task并发度控制,任意项目下,用户在同一时刻最多只能提交1000个Task。对于Graph及部分MPI类型的PAI作业,最大只允许1000个进程的作业。 列限制:表string列内容长度不允许超过8MB; SQL:

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

Hadoop资料整理导向

一、Hadoop快速入门 分布式计算开源框架Hadoop_入门实践 一篇不错的hadoop介绍文章 用 Hadoop 进行分布式数据处理---- 入门 Hadoop入门实验 Hadoop入门 一图解说Hadoop的发展历程 讨论:Hadoop社区与中国云计算开源展望 用Hadoop进行分布式数据处理入门篇 Hadoop入门简介 hadoop入门语录 为什么Hadoop一定是分布式计算的未来? Hadoop Ubuntu 学习笔记 二、Hadoop集群搭建 Hadoop集群安装 Hadoop超级安装手册 云计算的利刃:快速部署Hadoop集群 Hadoop学习笔记之二:部署与应用实例 ubuntu下hadoop的部署 ssh的无密码登陆 Hadoop的安装部署以及使用 Hadoop集群搭建 Hadoop中的集群配置和使用技巧 三、Hadoop分布式文件系统:架构和设计 大数据下的数据分析-Hadoop架构解析 Hadoop分布式文件系统:架构和设计要点 Hadoop的HDFS 四、Hadoop 命令和使用指南 Hadoop中的数据库访问 Hadoop in Practice 用Hadoop进行分布式并行编程 用Hadoop进行分布式并行编程, 第2 部分 用Hadoop进行分布式并行编程, 第3 部分 使用 Linux 和 Hadoop 进行分布式计算 Hadoop:HDFS权限管理用户指南 Hadoop命令手册 Hadoop Shell命令 利用Ant构建Hadoop高效开发环境 四、Hadoop Map/Reduce/ DistCp SMAQ:海量数据的存储计算和查询模型l 关于MapReduce-Hadoop权威指南连载l Hadoop学习笔记之:Hadoop的两个部分 EMC为企业提供基于Hadoop的大数据分析 针对Hadoop MapReduce的数据处理API Hadoop DistCp Hadoop Map/Reduce教程 Lucene-Hadoop, GFS中Map/Reduce的简单实现 六、Hadoop本地库 Hadoop本地库 七、Hadoop Streaming Hadoop Streaming Hadoop Streaming 编程 hadoop-Streaming学习 Hadoop Streaming框架使用(一) Hadoop的Streaming 八、Hadoop Archives Hadoop Archives 九、Hadoop On Demand Hadoop On Demand管理指南 十、Hadoop常见问题 大数据时代 Hadoop解决数据处理三瓶颈 Hadoop平台存在三个方面的挑战 Hadoop关于处理大量小文件的问题和解决方法 Hadoop使用常见问题以及解决方法(1) - [分布式] Hadoop使用常见问题以及解决方法(2) - [分布式] 十一、文档资料 hadoop最好的参考资料 hadoop权威指南中文版 官方文档 hadoop开发者杂志 十二、厂商与hadoop合作发展 戴尔将在服务器中预装开源Hadoop平台 微软SQL Server增加对Hadoop的支持 Dell与Cloudera 共推Hadoop 解决方案 IBM将在Hadoop上建立全新存储架构设计 EMC为企业提供基于Hadoop的大数据分析 Yahoo公布Hadoop的源代码 Cloudera的免费Hadoop Hadoop:Google核心技术的开源版本hadoop资料汇总.pdf

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

整理】Hadoop学习资料

Hadoop视频资料: http://pan.baidu.com/s/1o7YPdTC 注:有些视频是转载的,没有解压密码!so sorry!!! Hadoop运维全纪录: http://blog.51cto.com/zt/505 加入群【clouderahadoop】:258669058不定期发布资料的word文档、个人在工作中的遇见的bug和心得! Hadoop 的调优和运维对于 Hadoop 来说是很重要的一个环节。对于大规模数据集来说更是如此。 性能调优对于 Hadoop 来说无异于打通“任督二脉”,对于 Hadoop 的计算能力会有质的提升, 而运维之于 Hadoop 来说,就好像"金钟罩,铁布衫"一般,有了稳定的运维, Hadoop 才能在海量数据中大展拳脚,两者相辅相成,缺一不可。

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

吐血整理的Google Guava

一、概述 Guava 是由Google开发的基于Java的开源库,包含许多Google核心库,它有助于最佳编码实践,并有助于减少编码错误。它为集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等提供实用程序方法。 <!-- https://mvnrepository.com/artifact/com.google.guava/guava --> <dependency> <groupid>com.google.guava</groupid> <artifactid>guava</artifactid> <version>${laster.version}</version> </dependency> 源码包的简单说明 包路径 描述 com.google.common.annotations 普通注解类型 com.google.common.base 基本工具类库和接口 com.google.common.cache 缓存工具包,非常简单易用且功能强大的JVM内缓存 com.google.common.collect 带泛型的集合接口扩展和实现,以及工具类,这里你会发现很多好玩的集合 com.google.common.eventbus 发布订阅风格的事件总线 com.google.common.hash 哈希工具包 com.google.common.io I/O工具包 com.google.common.math 原始算术类型和超大数的运算工具包 com.google.common.net 网络工具包 com.google.common.primitives 八种原始类型和无符号类型的静态工具包 com.google.common.reflect 反射工具包 com.google.common.util.concurrent 多线程工具包 二、使用手册 2.1 基本工具 [Basic utilities] 2.1.1 使用和避免null 到目前为止,臭名昭著的 NullPointerException 是导致Java应用程序失败的最常见原因。通过查看Google底层代码库,我们发现95%的集合类不接受null值作为元素。我们认为, 相比默默地接受null,使用快速失败操作拒绝null值对开发者更有帮助。此外,Null的含糊语义让人很不舒服。Null很少可以明确地表示某种语义,例如,Map.get(key)返回Null时,可能表示map中的值是null,亦或map中没有key对应的值。Null可以表示失败、成功或几乎任何情况。使用Null以外的特定值,会让你的逻辑描述变得更清晰。鉴于这些原因,很多Guava工具类对Null值都采用快速失败操作,除非工具类本身提供了针对Null值的因变措施。 大多数情况下,开发人员使用null表明的是某种缺失情形:可能是已经有一个默认值,或没有值,或找不到值。例如,Map.get返回null就表示找不到给定键对应的值。Guava用 Optional<t> 表示可能为null的T类型引用,一个Optional实例可能包含非null的引用,也可能什么也不包括。它从不说包含的是null值,而是用存在或缺失来表示,但Optional从不会包含null值引用。 创建Optional实例(以下都是静态方法): 方法 描述 Optional.of(T) 创建指定引用的Optional实例,若引用为null则快速失败 Optional.absent() 创建引用缺失的Optional实例 Optional.fromNullable(T) 创建指定引用的Optional实例,若引用为null则表示缺失 用Optional实例查询引用(以下都是非静态方法): 方法 描述 boolean isPresent() 如果Optional包含非null的引用(引用存在),返回true T get() 返回Optional所包含的引用,若引用缺失,则抛出java.lang.IllegalStateException T or(T) 返回Optional所包含的引用,若引用缺失,返回指定的值 T orNull() 返回Optional所包含的引用,若引用缺失,返回null Set asSet() 返回Optional所包含引用的单例不可变集。<br>如果引用存在,返回一个只有单一元素的集合,如果引用缺失,返回一个空集合。 2.1.2 常见Object方法 equals 当一个对象中的字段可以为null时,实现 Object.equals 会很痛苦,因为不得不分别对它们进行null检查。使用 Objects.equal 帮助你执行null敏感的equals判断,从而避免抛出NullPointerException。例如: package org.dllwh.guava.basicutilities; import com.google.common.base.Objects; public final class ObjectHelper { public static void main(String[] args) { System.out.println(Objects.equal("a", "a")); System.out.println(Objects.equal(null, "a")); System.out.println(Objects.equal("a", null)); System.out.println(Objects.equal(null, null)); } } hashCode 用对象的所有字段作散列[hash]运算应当更简单。Guava的 Objects.hashCode(Object...) 会对传入的字段序列计算出合理的、顺序敏感的散列值。你可以使用Objects.hashCode(field1, field2, …, fieldn)来代替手动计算散列值。 2.1.3 前置条件 Guava在 Preconditions 类中提供了若干前置条件判断的实用方法,让方法调用的前置条件判断更简单。 方法声明(不包括额外参数) 描述 检查失败时抛出的异常 checkArgument(boolean expression) 检查boolean是否为true,用来检查传递给方法的参数 IllegalArgumentException checkNotNull(T) 检查value是否为null,该方法直接返回value NullPointerException checkState(boolean expression) 用来检查对象的某些状态 IllegalStateException checkElementIndex(int index, int size) 检查index作为索引值对某个列表、字符串或数组是否有效。index>=0 && index<size IndexOutOfBoundsException checkPositionIndex(int index, int size) 检查index作为位置值对某个列表、字符串或数组是否有效。index>=0 && index<=size checkPositionIndexes(int start, int end, int size) 检查[start, end]表示的位置范围对某个列表、字符串或数组是否有效 IndexOutOfBoundsException 每个方法都有三个变种: 没有额外参数:抛出的异常中没有错误消息; 有一个Object对象作为额外参数:抛出的异常使用Object.toString() 作为错误消息; 有一个String对象作为额外参数,并且有一组任意数量的附加Object对象:这个变种处理异常消息的方式有点类似printf,但考虑GWT的兼容性和效率,只支持%s指示符。 2.2 强大的集合工具类[Collections] 任何对JDK集合框架有经验的程序员都熟悉和喜欢 java.util.Collections 包含的工具方法。Guava对JDK集合的扩展,提供了更多的工具方法:适用于所有集合的静态方法,这是Guava最流行和成熟的部分之一。在Guava Collections中,Guava提供了一些用于处理这些集合实例的类,接下来用相对直观的方式把工具类与特定集合接口的对应关系归纳如下: 集合接口 属于JDK还是Guava 对应的Guava工具类 Collection JDK Collections2,不要和java.util.Collections混淆 List JDK Lists Set JDK Sets SortedSet JDK Sets Map JDK Maps SortedMap JDK Maps Queue JDK Queues Multiset Guava Multisets Multimap Guava Multimaps BiMap Guava Maps Table Guava Tables 2.2.1 Lists Lists是Guava Collections中提供的用于处理List实例的实用类,翻开源代码,我们看到,其内部使用了静态工厂方法代替构造器,提供了许多用于List子类构造和操作的静态方法,我们简单的依次进行说明,如下: 方法 描述 newArrayList() 构造一个可变的、空的ArrayList实例。 newArrayList(E... elements) 构造一个可变的包含传入元素elements的ArrayList实例 newArrayList(Iterable<!--? extends E--> elements) 构造一个可变的包含传入元素elements的ArrayList实例 newArrayListWithCapacity(int initialArraySize) 构造一个分配 指定空间大小的ArrayList实例 newArrayListWithExpectedSize(int estimatedSize) 构造一个期望长度为estimatedSize的ArrayList实例 newLinkedList() 构造一个空的LinkedList实例 newCopyOnWriteArrayList() 构造一个空的CopyOnWriteArrayList实例 除了静态工厂方法和函数式编程方法,Lists 为List类型的对象提供了若干工具方法: 方法 描述 asList(E first, E[] rest) 返回一个不可变的List asList(E first,E second, E[] rest) partition(List list, int size) 根据size传入的List进行切割,切割成符合要求的小的List并存入一个新的List对象中返回 charactersOf(String string) 将传进来的String分割为单个的字符,并存入到一个新的List对象中返回 charactersOf(CharSequence sequence) 将传进来的sequence分割为单个的字符,并存入到一个新的List对象中返回 reverse(List list) 返回一个传入List内元素倒序后的List。 示例如下: public final class ListsHelper { public static void main(String[] args) { /** * 一些构造List实例的方法很简单 * 如:newArrayList(),newLinkedList()等 * 这里不再赘述 */ String str = "i love u"; String[] strs = {"i like u", "i miss u"}; /** * asList:返回一个不可变的List * 其中包含指定的第一个元素和附加的元素数组组成 * 修改这个数组将反映到返回的List上 */ List<string> list = Lists.asList(str, strs); System.out.println(list); // 对strs数组的修改会反映到List中 strs[1] = "i hate u"; System.out.println(list); /** * partition:根据size传入的List进行切割,切割成符合要求的小的List * 并将这些小的List存入一个新的List对象中返回 */ List<list<string>&gt; lists = Lists.partition(list, 2); System.out.println(lists); /** * charactersOf:将传进来的String或者CharSequence分割为单个的字符 * 并存入到一个ImmutableList对象中返回 * ImmutableList:一个高性能、不可变的、随机访问列表的实现 */ ImmutableList<character> characters = Lists.charactersOf("realfighter"); System.out.println(characters); /** * reverse:返回一个传入List内元素倒序后的List */ List<string> reverse = Lists.reverse(list); System.out.println(reverse); } } 2.2.2 Maps Guava Maps 对java Map封装和升级,实现强大、简洁应用方式。首先让我们看看Guava创建Map方法: 方法 描述 Maps.newConcurrentMap() 构造ConCurrentHashMap Maps.newEnumMap() Maps.newHashMap(); 构造HashMap Maps.newHashMapWithExpectedSize(int expectedSize) 初始化一定大小的的map集合 Maps.newIdentityHashMap(); Maps.newLinkedHashMap(); 构造LinkedHashMap Maps.newLinkedHashMapWithExpectedSize(int expectedSize) 初始化一定大小的的map集合 Maps.newTreeMap(); 构造TreeMap 方法 描述 asMap Set转Map,函数式接口用于通过Set的元素值获取Map的value值 difference 通过Map的key计算left和right的差值,MapDifference包含 left – right、right – left及left与right相交这三部分信息 filterEntries 通过Map的Entry(key和value)过滤Map,函数式接口为通过Entry产生的过滤条件 filterKeys 通过Map的key过滤Map,函数式接口为通过key产生的过滤条件 filterValues 通过Map的value过滤Map,函数式接口为通过value产生的过滤条件 subMap 通过Range确定的key的范围分割Map,即求子Map toMap list转Map,函数式接口用于通过list元素确定Map的value,如果list中存在重复元素,会丢弃重复元素。 2.2.3 Sets 方法 描述 newHashSet() newLinkedHashSet() newTreeSet() newConcurrentHashSet() 2.3 字符串处理[Strings] 2.3.1 字符串处理 Strings Strings 类主要提供了对字符串的一些操作。主要方法如下: 方法 描述 nullToEmpty(String string) null字符串转空字符串 emptyToNull(String string) 空字符串转null字符串 isNullOrEmpty(String string) 判断字符串为null或空字符串 padStart(String string, int minLength, char padChar) 如果string的长度小于minLeng,在string前添加padChar,直到字符串长度为minLeng padEnd(String string, int minLength, char padChar) 和padStart类似,不过是在尾部添加新字符串 repeat(String string, int count) commonPrefix(CharSequence a, CharSequence b) 返回共同的前缀 commonSuffix(CharSequence a, CharSequence b) 返回共同的后缀 lenientFormat(String template,Object... args) 2.3.2 连接器[Joiner] Joiner 是用来连接字符串的,它能以指定的字符对多个字符串进行连接。比如,我们要将一个List中的元素用逗号连接起来,这是日常开发中很常见的逻辑处理,那以前我们可能会这样写: List<string> list = Lists.newArrayList("a","b","c"); StringBuffer buffer = new StringBuffer(); for(int i = 0; i &lt; list.size(); i++){ if(i &gt; 0){ buffer.append(","); } buffer.append(list.get(i)); } System.out.println(buffer.toString()); 用分隔符把字符串序列连接起来也可能会遇上不必要的麻烦,如果字符串序列中含有null,那连接操作会更难,而Fluent风格的[Joiner让连接字符串更简单。 Joiner.on(";").skipNulls().join("hello World", null, "独泪了无痕"); Joiner也可以用来连接对象类型,在这种情况下,它会把对象的toString()值连接起来。 // return "a,b,c" Joiner.on(",").join(Arrays.asList("a","b","c")); // return "id=123&amp;name=dllwh" Joiner.on("&amp;").withKeyValueSeparator("=").join(ImmutableMap.of("id", "123", "name", "dllwh")); 常用方法如下: 方法 描述 on(String) 静态工厂方法,生成一个新的 Joiner 对象,参数为连接符 skipNulls() 如果元素为空,则跳过 useForNull(String) 如果元素为空,则用这个字符串代替 join 要连接的数组/链表 appendTo 在第一个参数后面新加上 拼接后的字符串 withKeyValueSeparator(String) 得到 MapJoiner,连接Map的键、值 > joiner实例总是不可变的,用来定义joiner目标语义的配置方法总会返回一个新的joiner实例,这使得joiner实例都是线程安全的,所以可以将其定义为static final常量。 2.3.3 拆分器[Splitter] Splitter 能将一个字符串按照分隔符生成字符串集合,是 Joiner的反向操作。常用方法如下: 方法 描述 Splitter.on(char) 按单个字符拆分 Splitter.on(CharMatcher) 按字符匹配器拆分 Splitter.on(String) 按字符串拆分 Splitter.on(Pattern) 按正则表达式拆分 Splitter.onPattern(String) 按正则表达式拆分 Splitter.fixedLength(int) 按固定长度拆分;最后一段可能比给定长度短,但不会为空。 omitEmptyStrings() 从结果中自动忽略空字符串 trimResults() 移除结果字符串的前导空白和尾部空白 trimResults(CharMatcher) 给定匹配器,移除结果字符串的前导匹配字符和尾部匹配字符 limit(int) 限制拆分出的字符串数量 withKeyValueSeparator(String) 得到 MapSplitter,拆分成Map的键、值。<br>注意,这个对被拆分字符串格式有严格要求,否则会抛出异常 示例如下: public final class SplitterHelper { public static void main(String[] args) { String string = " ,a,b,"; System.out.println(Splitter.on(",").split(string)); System.out.println(Splitter.on(",").trimResults().split(string)); System.out.println(Splitter.on(",").omitEmptyStrings().split(string)); System.out.println(Splitter.on(",").trimResults().omitEmptyStrings().split(string)); // 根据长度拆分 string = "12345678"; System.out.println(Splitter.fixedLength(2).split(string)); // 拆分成Map System.out.println(Splitter.on("&amp;").withKeyValueSeparator("=").split("id=123&amp;name=dllwh")); } } > splitter实例总是不可变的,用来定义splitter目标语义的配置方法总会返回一个新的splitter实例,这使得splitter实例都是线程安全的 2.3.4 字符匹配器[CharMatcher] > CharMatcher,将字符的匹配和处理解耦,并提供丰富的方法供你使用! CharMatcher本身提供了很多CharMatcher实现类,如下: 方法 描述 ANY 匹配任何字符 NONE 不匹配所有字符 WHITESPACE 匹配所有空白字符 BREAKING_WHITESPACE 匹配所有可换行的空白字符(不包括非换行空白字符,例如"\u00a0") INVISIBLE 匹配所有看不见的字符 DIGIT 匹配ASCII数字 JAVA_LETTER 匹配字母, 使用 Charater.isLetter() 实现 AVA_DIGIT 匹配UNICODE数字, 使用 Character.isDigit() 实现 JAVA_LETTER_OR_DIGIT 匹配数字或字母 JAVA_ISO_CONTROL 匹配ISO控制字符, 使用 Charater.isISOControl() 实现 JAVA_LOWER_CASE 匹配小写 JAVA_UPPER_CASE 匹配大写 ASCII 匹配是否是ASCII字符 SINGLE_WIDTH 匹配单字宽字符, 如中文字就是双字宽 构造对象 方法 描述 CharMatcher.is(char match) 返回匹配指定字符的Matcher CharMatcher.isNot(char match) 返回不匹配指定字符的Matcher CharMatcher.anyOf(CharSequence sequence) 返回匹配sequence中任意字符的Matcher CharMatcher.noneOf(CharSequence sequence) 返回不匹配sequence中任何一个字符的Matcher CharMatcher.inRange(char startInclusive, char endIncludesive) 返回匹配范围内任意字符的Matcher CharMatcher.negate() 返回以当前Matcher判断规则相反的Matcher CharMatcher.and(CharMatcher other) 返回与other匹配条件组合做与来判断的Matcher CharMatcher.or(CharMatcher other) 返回与other匹配条件组合做或来判断的Matcher CharMatcher提供了多种多样的方法操作CharSequence中的特定字符。其中最常用的罗列如下: 方法 描述 boolean matchesAnyOf(CharSequence sequence) 只要sequence中有任意字符能匹配Matcher,返回true boolean matchesAllOf(CharSequence sequence) sequence中所有字符都能匹配Matcher,返回true boolean matchesNoneOf(CharSequence sequence) sequence中所有字符都不能匹配Matcher,返回true int indexIn(CharSequence sequence) 返回sequence中匹配到的第一个字符的坐标 int indexIn(CharSequence sequence, int start) 返回从start开始,在sequence中匹配到的第一个字符的坐标 int lastIndexIn(CharSequence sequence) 返回sequence中最后一次匹配到的字符的坐标 int countIn(CharSequence sequence) 返回sequence中匹配到的字符计数 String removeFrom(CharSequence sequence) 删除sequence中匹配到到的字符并返回 String retainFrom(CharSequence sequence) 保留sequence中匹配到的字符并返回 String replaceFrom(CharSequence sequence, char replacement) 替换sequence中匹配到的字符并返回 String trimFrom(CharSequence sequence) 删除首尾匹配到的字符并返回 String trimLeadingFrom(CharSequence sequence) 删除首部匹配到的字符 String trimTrailingFrom(CharSequence sequence) 删除尾部匹配到的字符 String collapseFrom(CharSequence sequence, char replacement) 将匹配到的组(连续匹配的字符)替换成replacement String trimAndCollapseFrom(CharSequence sequence, char replacement) 先trim在replace 2.3.5 字符集[Charsets] Charsets 针对所有Java平台都要保证支持的六种字符集提供了常量引用。尝试使用这些常量,而不是通过名称获取字符集实例。 public final class Charsets { @GwtIncompatible public static final Charset US_ASCII = Charset.forName("US-ASCII"); public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); public static final Charset UTF_8 = Charset.forName("UTF-8"); @GwtIncompatible public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); @GwtIncompatible public static final Charset UTF_16LE = Charset.forName("UTF-16LE"); @GwtIncompatible public static final Charset UTF_16 = Charset.forName("UTF-16"); private Charsets() { } } 2.4 原生类型[Primitives] Java的原生类型就是指基本类型:byte、short、int、long、float、double、char和boolean。原生类型不能当作对象或泛型的类型参数使用,这意味着许多通用方法都不能应用于它们。Guava提供了若干通用工具,包括原生类型数组与集合API的交互,原生类型和字节数组的相互转换,以及对某些原生类型的无符号形式的支持。 原生类型 Guava工具类(com.google.common.primitives) byte Bytes,SignedBytes, UnsignedBytes short Shorts int Ints, UnsignedInteger, UnsignedInts long Longs UnsignedLong, UnsignedLongs float Floats double Doubles char Chars boolean Booleans </string></string></character></list<string></string></t>

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

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

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。