Atomic类用于保证变量操作的原子性,先记录,有时间再进行研究 :-(
Java实现回形遍历的代码
本来以为这样的回形是有规律可循的,但是找了好长时间没找到,看来只能用遍历了。
x,y的使用有些乱,读者自己理一下吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
private String huiXingBianLi(){ final int FLAG_RIGHT = 0; final int FLAG_DOWN = 1; final int FLAG_LEFT = 2; final int FLAG_UP = 3; String resultStr = ""; int flag = FLAG_RIGHT; final int countx = 10; final int county = 11; int x = 0, y = 0; int minx = 0, maxx = county - 1, miny = 1, maxy = countx - 1; int[][] result = new int[countx][county]; int i = 0; while(i < countx * county){ result[y][x] = ++i; if(flag == FLAG_RIGHT){ if(x >= maxx){ maxx--; y++; flag = FLAG_DOWN; continue; }else{ x++; } } if(flag == FLAG_DOWN){ if(y >= maxy){ maxy--; x--; flag = FLAG_LEFT; continue; }else{ y++; } } if(flag == FLAG_LEFT){ if(x <= minx){ minx++; y--; flag = FLAG_UP; continue; }else{ x--; } } if(flag == FLAG_UP){ if(y <= miny){ miny++; x++; flag = FLAG_RIGHT; continue; }else{ y--; } } } resultStr = ""; for(int i1=0; i1 < countx ; i1++){ for(int j1 = 0; j1 < county ; j1++){ if(j1 == 0){ resultStr += String.format(" %03d", result[i1][j1]); }else { resultStr += "..." + String.format("%03d", result[i1][j1]); } } resultStr += "\n"; } return resultStr; } |
结果展示:
1 2 3 4 5 6 7 8 9 10 |
001...002...003...004...005...006...007...008...009...010...011 038...039...040...041...042...043...044...045...046...047...012 037...068...069...070...071...072...073...074...075...048...013 036...067...090...091...092...093...094...095...076...049...014 035...066...089...104...105...106...107...096...077...050...015 034...065...088...103...110...109...108...097...078...051...016 033...064...087...102...101...100...099...098...079...052...017 032...063...086...085...084...083...082...081...080...053...018 031...062...061...060...059...058...057...056...055...054...019 030...029...028...027...026...025...024...023...022...021...020 |
Android开发中使用jni
一、jni背景知识
jni是Java Native Interface的缩写,jni并不是Android开发的特性,而是在java的早期版本中就已经支持了,用于java层和Native层进行通讯的中间桥梁,大部分情况下使用c和c++进行编写,也可以使用其他的语言编写,只要满足约定的接口就可以。
二、Jni的副作用
Jni有以下副作用:
1、不再具有跨平台可移植性,如果移植到其他平台,需要开发Native层的相关代码
2、Native层的程序如果有问题将会导致java层的程序崩溃
三、开发步骤简述(Ubuntu 16 + openjdk-8-jdk)
1、在java代码中定义Native函数,比如java文件名为JniTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class JniTest{ static { System.loadLibrary("jnitest"); } native int calc(int i1, int i2); public static void main(String args[]){ JniTest jnitest = new JniTest(); int sum = jnitest.calc(322, 21); System.out.print(sum); } } |
2、使用javac编译java文件,javac JniTest.java
3、使用javah工具传入java类名,生成native层的头文件,javah JniTest,此时目录下会有一个JniTest.h
4、新建一个JniTest.cc的文件,并添加如下内容:
1 2 3 4 5 6 |
#include "JniTest.h" JNIEXPORT jint JNICALL Java_JniTest_calc (JNIEnv *env, jobject obj, jint i1, jint i2){ return i1 + i2; }; |
5、将navtive层的代码编译成so库,命令如下:
1 2 |
gcc -I/usr/lib/jvm/java-8-openjdk-amd64/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux -Wall -g -fPIC -c JniTest.cc -o jnitest.o gcc -shared jnitest.o -o libjnitest.so |
6、在java层使用System.loadLibrary(“jnitest”);加载动态库,并调用函数,见第1中的java代码
参考链接:
https://baike.baidu.com/item/JNI/9412164?fr=aladdin
Java中常用的日期操作
直接上代码
Calendar calendar = Calendar.getInstance();
//显示当前时间
System.out.println(calendar.getTime());
//各种日期格式化
SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss.SSS”);
String str = format.format(calendar.getTime());
System.out.println(str);
format = new SimpleDateFormat(“yyyyMMdd”);
str = format.format(calendar.getTime());
System.out.println(str);
format = new SimpleDateFormat(“yyyy/MM/dd”);
str = format.format(calendar.getTime());
System.out.println(str);
format = new SimpleDateFormat(“yyyy/M/d”);
str = format.format(calendar.getTime());
System.out.println(str);
//获取时间戳
str = String.valueOf(calendar.getTimeInMillis());
System.out.println(“时间戳: ” + str);
//减去一天
calendar.add(Calendar.DAY_OF_YEAR, -1);
format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss.SSS”);
str = format.format(calendar.getTime());
System.out.println(str);
//减去一个月
calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, -1);
format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss.SSS”);
str = format.format(calendar.getTime());
System.out.println(str);
//减去一年
calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, -1);
format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss.SSS”);
str = format.format(calendar.getTime());
System.out.println(str);
//只获取日期,不包含时间
calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss.SSS”);
str = format.format(calendar.getTime());
System.out.println(str);
//获取本月的第一天
calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_MONTH, 1);
format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss.SSS”);
str = format.format(calendar.getTime());
System.out.println(str);
//时间戳字符串转日期时间
calendar = Calendar.getInstance();
str = String.valueOf((calendar.getTimeInMillis() – 60 * 1000) ); //减去一分钟
calendar.setTimeInMillis(Long.parseLong(str));
format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss.SSS”);
str = format.format(calendar.getTime());
System.out.println(str);
当continue遇上finally,continue执行后仍会执行finally中的代码,如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 |
public static void main(String[] args){ for(int i = 1; i < 11; i++){ try{ if(i % 5 == 0){ System.out.println("continue: i = " + i); continue; } } finally { System.out.println("finally: i = " + i); } } } |
运行输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 |
finally: i = 1 finally: i = 2 finally: i = 3 finally: i = 4 continue: i = 5 finally: i = 5 finally: i = 6 finally: i = 7 finally: i = 8 finally: i = 9 continue: i = 10 finally: i = 10 |
StringBuilder几种清空方法的效率比较
一共有三种方法可以实现StringBuilder的清空
- New一个新的StringBuilder
- 使用StringBuilder的delete方法
- 使用StringBuilder的setLength方法
下面通过代码验证三种方法的效率
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
public class StringBuilderClearTest { public static void main(String[] args){ long time = System.currentTimeMillis(); System.out.println("begin: " + time); StringBuilder sbMain1 = new StringBuilder(); StringBuilder sbMain2 = new StringBuilder(); StringBuilder sbMain3 = new StringBuilder(); StringBuilder sb1 = null; for(int i=0; i<1000000; i++){ sb1 = new StringBuilder("a1"); sb1.append("a2"); sb1.append("a3"); sbMain1.append(sb1); } long time1 = System.currentTimeMillis(); StringBuilder sb2 = new StringBuilder(); for(int i=0; i<1000000; i++){ sb2.delete(0, sb2.length()); sb2.append("b1"); sb2.append("b2"); sb2.append("b3"); sbMain2.append(sb2); } long time2 = System.currentTimeMillis(); StringBuilder sb3 = new StringBuilder(); for(int i=0; i< 1000000; i++){ sb3.setLength(0); sb3.append("c1"); sb3.append("c2"); sb3.append("c3"); sbMain3.append(sb3); } long time3 = System.currentTimeMillis(); System.out.println(sbMain1.length()); System.out.println(sbMain2.length()); System.out.println(sbMain3.length()); System.out.println("New耗时: " + (time1 - time)); System.out.println("delete耗时: " + (time2 - time1)); System.out.println("setLength: " + (time3 - time2)); } } |
测试了十几次,选了一次比较有代表性的结果:
1 2 3 |
New耗时 90 delete耗时: 73 setLength: 63 |
由结果可见setLength是最快的,delete不相上下,new是最慢的
Java中如何更好的使用枚举类型
1. 使用enum类型:
在Java中有 enum类型可以用于枚举,但是每个enum的类型都是做为一个类来处理,对于要求效率较高的程序不是一个很好的选择,android官方也不推荐在应用开发中使用此类型。
2. 定义整形常量
就是定义static final的整形值,这样虽然效率高,但是不方便查看代码和进行方法参数的描述,如下面的代码虽然加了注释,但是如果常量很多,还是无法轻松定位到想要查看的常量,有多个名称相似的常量时还容易混淆,甚至使用了错误的常量。
1 2 3 4 5 6 7 8 9 10 11 |
//声音警告方式 public static final int ALERT_TYPE_SOUND = 0; //振动警告方式 public static final int ALERT_TYPE_VERBERITE = 1; //文本便签 public static final int NOTETYPE_TEXT = 0; //语音便签 public static final int NOTETYPE_VOICE = 1; //手写便签 public static final int NOTETYPE_HANDWRITE = 2; |
如下是常量做为方法的参数时的描述
1 2 3 4 5 6 7 8 9 10 |
/** * * @param notetype 便签类型,可能是以下几种定义中的一种 * @see Const.NOTETYPE_TEXT * @see Const.NOTETYPE_VOICE * @see Const.NOTETYPE_HANDWRITE */ public void showNote(int notetype){ } |
3. 在一个类中定义静态常量
将常量定义到一个类中,容易限制这些常量的范围,便于查看,而且在使用常量方法的方法描述里易于写注释,如下是常量的定义
1 2 3 4 5 |
public static final class NoteType{ public static final int TEXT = 0; public static final int VOICE = 1; public static final int HANDWRITE = 2; } |
而在方法描述中,只链接到Const.NoteType即可
1 2 3 4 5 6 7 |
/** * @param noteType 便签类型,类型的定义请查看Const.NoteType * @see Const.NoteType */ public void showNote(int noteType){ } |
Java中加号和StringBuilder进行字符串连接的效率比较
注意:在Java8中默认使用StringBuilder进行字符串进行拼接
下面代码对字符串进行10000次加号连接和StringBuilder连接操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public class StringBuilderTest { public static void main(String[] args){ long time = System.currentTimeMillis(); System.out.println("begin: " + time); String str = ""; for(int i=0; i<10000; i++){ str = str + "a1" + 1 + "a2"; } long time1 = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for(int i=0; i<10000; i++){ //sb.delete(0, sb.length()); sb.append("a1"); sb.append(1); sb.append("a2"); } long time2 = System.currentTimeMillis(); System.out.println(str); System.out.println(sb.toString()); System.out.println("加号耗时: " + (time1 - time)); System.out.println("StringBuilder耗时: " + (System.currentTimeMillis() - time1)); } } |
最后得到的结果如下:
1 2 |
加号耗时: 563 StringBuilder耗时: 7 |
由此可见效率差了80倍
注意:
- StringBuffer为线程安全的字符串操作类,由于需要处理多线程同步问题,效率比StringBuilder要低
关于Java中垃圾回收机制的一些理解
今天看java的垃圾回收,突然想到java的垃圾回收和排档(或者食堂)的餐盘回收有点类似。
食堂的餐盘回收一般会有以下几种方式:一是用餐者自行将餐盘放回回收处,二是食堂有专门的服务员来回收餐盘。
java的垃圾回收机制和第二种很相似,有垃圾回收器这个“服务员”来回收程序运行中产生的不再使用的对象。
服务员会定时的检查放在餐桌上的盘子,看是否还有人在使用,如果没人使用就会进行回收