Java 的函数糖

Nov 22, 2017 12:25:03 AM

作者:zozohwendal

什么是函数糖?

Java 的语法比 C/C++ 友好很多, 因为它设计之初,就是为了考虑到程序员的使用是否舒适。当然很多事情愿望是美好的,现实是残酷的。Java 语言本身的语法仍然不可避免的带有着 10年前那种的僵硬和严谨。这里是一些小小的尝试,你会发现,大多数情况,通过一些静态函数,一行代码完全可以做很多事情, 而且比“甜甜”的 Ruby 也差不了太多。

你可以查看 org.nutz.langGit@OSC镜像 下的源代码。为了便于你学习,我将里面部分最常用的用法列在文档里,便于快速学习查看。

我希望在 80% 以上的情况下,这些函数能让你有效的缩短你代码的体积,并且增加代码的可读性。

异常

创建异常

  • 根据格式化字符串,生成运行时异常
  1. throw Lang.makeThrow("Error for %d [%s]", obj.getId(), obj.getName());
  • 根据格式化字符串,生成一个指定的异常。
  1. throw Lang.makeThrow(SQLException.class, "Error for %d [%s]", obj.getId(), obj.getName());
  • 未实现的运行时异常
  1. throw Lang.noImplement();

包裹异常

  • 用运行时异常包裹抛出对象,如果抛出对象本身就是运行时异常,则直接返回。
  1. throw Lang.wrapThrow(e);
  • 用一个指定可抛出类型来包裹一个抛出对象。这个指定的可抛出类型需要有一个构造函数 接受 Throwable 类型的对象
  1. throw Lang.wrapThrow(e, SQLException.class);
  • 将一个或者多个异常组合抛出
  1. throw Lang.comboThrow(e1,e2,e3);
  • 将抛出对象包裹成运行时异常,并增加自己的描述
  1. throw Lang.wrapThrow(e, "Error for %d [%s]", obj.getId(), obj.getName());

对象

  • 比较对象: 支持数组,集合,和容器
  1. return Lang.equals(map1, map2);
  • 显示对象
  1. return Dumps.obj(pojo);
  • 是否包括
  1. return Lang.contains(myArray, ele);
  • 遍历
  1. Lang.each(obj, new Each<Object>(){
  2. public void invoke(int i, T ele, int length){
  3. obj 可以是集合,数组,Map,普通对象.
  4. 普通对象的话,则会传给本匿名类的 ele
  5. }
  6. });

容器转换

  • 数组 to Map
  1. Pet[] pets = new Pet[3];
  2. ... // 为数组赋值
  3. // 将把 Pet 对象的 name 字段的值作为 Key, 创建一个 Map
  4. Map<String,Pet> petMap = Lang.array2map(HashMap.class, pets, "name");
  • 数组 to 数组
  1. Pet[] pets = new Pet[3];
  2. String[] ss = Lang.array2array(pets, String.class);
  • 集合 to 数组
  1. List<Pet> pets = new ArrayList<Pet>();
  2. ... // 为列表赋值
  3. Pet[] petArray = Lang.collection2array(pets);
  • 集合 to 列表
  1. Queue<Pet> pets = new ArrayDeque<Pet>();
  2. ... // 为队列赋值
  3. List<Pet> list = Lang.collection2list(pets);
  • 集合 to Map
  1. Queue<Pet> pets = new ArrayDeque<Pet>();
  2. ... // 为队列赋值
  3. // 将把 Pet 对象的 name 字段的值作为 Key, 创建一个 Map
  4. Map<String,Pet> petMap = Lang.collection2map(HashMap.class, pets, "name");
  • Map to 对象
  1. return Lang.map2Object(map,Pet.class);

对象模拟

  • 生成数组
  1. String[] ss = Lang.array("A","B","C");
  • 从字符串生成 Reader
  1. Reader reader = Lang.inr("ABCDEF");
  • 从字符串生成 InputStream
  1. InputStream ins = Lang.ins("ABCDEF");
  • 从字符串生成 Map
  1. Map<String,Object> map = Lang.map("{a:10, b:'ABC', c:true}");
  • 从字符串生成 List
  1. List<Object> list = Lang.list("[true, 23, 'ABC']");

XML

  • 创建 DocumentBuilder
  1. return Xmls.xmls();
  • 解析 XML 文档
  1. Document xmlDoc = Xmls.xml(Files.findFile("~/my.xml"));
  • 读取某个子元素内容
  1. Element ele = ... // 假设你取到了一个 Element
  2. String txt = Xml.get(ele, "abc"); // 获取 ele 下的 <abc> 的文本内容并去掉前后空白

字符串操作

判断

  • 是否为空串
  1. assertTrue(Strings.isEmpty(""));
  • 是否为空白
  1. assertTrue(Strings.isBlank("\t \r\n"));
  • 是否被特定字符包裹
  1. assertTrue(Strings.isQuoteBy("[ABC]", '[', ']'));
  2. // 忽略空白
  3. assertTrue(Strings.isQuoteByIgnoreBlank(" \t [ABC]\r\n ", '[', ']'));
  • 集合中的最长串
  1. assertEquals(3, Strings.maxLength((String[]){"A","ABC","BC"}));
  2. // 集合
  3. assertEquals(3, Strings.maxLength(Lang.list("['A','ABC','BC']")));
  • 如果字符为null,返回特定默认值
  1. assertEquals("abc", Strings.sNull(null, "abc"));
  • 如果字符为空白,返回特定默认值
  1. assertEquals("abc", Strings.sBlank(" \n\t", "abc"));

修改

  • 首字母大写
  1. assertEquals("Abc", Strings.capitalize("abc"));
  • 首字母小写
  1. assertEquals("aBC", Strings.lowerFirst("ABC"));
  • 切除首尾空白
  1. assertEquals("ABC", Strings.trim("\t ABC \r\n "));
  • 左填充 (居右),当无法填充时不会按照指定的长度截断原字符串
  1. assertEquals("00FE", Strings.alignRight("FE", 4, '0'));
  2. assertEquals("FFFF", Strings.alignRight("FFFF", 2, '0'));
  • 右填充 (居左),当无法填充时不会按照指定的长度截断原字符串
  1. assertEquals("FE00", Strings.alignLeft("FE", 4, '0'));
  2. assertEquals("FFFF", Strings.alignLeft("FFFF", 2, '0'));
  • 固定长度左填充 (居右),当无法填充时将按照指定的长度截断原字符串
  1. assertEquals("00FE", Strings.cutRight("FE", 4, '0'));
  2. assertEquals("CD", Strings.cutRight("ABCD", 2, '0'));
  • 固定长度右填充 (居左),当无法填充时将按照指定的长度截断原字符串
  1. assertEquals("FE00", Strings.cutLeft("FE", 4, '0'));
  2. assertEquals("AB", Strings.cutLeft("ABCD", 2, '0'));

转换

  • 二进制形式字符串
  1. assertEquals("0110", Strings.fillBinary(6, 4));
  • 十六进制形式字符串
  1. assertEquals("00FF", Strings.fillHex(255, 4));
  • 拆分数组 (忽略空白元素)
  1. assertEquals(3, Strings.splitIgnoreBlank("A,B,C"));
  2. assertEquals(3, Strings.splitIgnoreBlank(",A,B,,C,"));

创建重复

  1. // 重复字符
  2. assertEquals("---", Strings.dup('-', 3));
  3. // 重复字串
  4. assertEquals("ABCABCABC", Strings.dup("ABC", 3));

文件操作

查找

  • 从 CLASSPATH 下或从指定的本机器路径下寻找一个文件
  1. return Files.findFile("org/nutz/lang/Lang.class");
  • 根据正则式,从压缩文件中获取文件
  1. return Files.findEntryInZip(new ZipFile("D:/nutz.jar"), "org/nutz/lang/Lang.class");
  • 搜索一个类同一包下面的所有类
  1. return Resources.scanClass(Lang.class);

创建-删除-拷贝

  • 创建新文件,如果父目录不存在,也一并创建
  1. Files.createNewFile(new File("D:/demo/abc.txt"));
  • 创建新目录,如果父目录不存在
  1. Files.makeDir(new File("D:/demo/abc"));
  • 强行删除一个目录,包括这个目录下所有的子目录和文件
  1. Files.deleteDir(new File("D:/demo/abc"));
  • 清除一个目录里所有的内容
  1. Files.clearDir(new File("D:/demo/abc"));
  • 将一个目录下的特殊名称的目录彻底删除,比如 '.svn' 或者 '.cvs'
  1. Files.cleanAllFolderInSubFolderes(new File("D:/demo"), ".svn");
  • 文件拷贝
  1. Files.copyFile(new File("D:/a/b/c.txt"), new File("E:/a/b/e.txt"));
  • 目录拷贝
  1. Files.copyDir(new File("D:/a/b/c"), new File("E:/a/b/e"));

读取-写入

  • 读取文件全部内容 - UTF-8
  1. String txt = Files.read("D:/abc.txt");
  2. 或者
  3. String txt = Lang.readAll(Streams.fileInr("D:/abc.txt"));
  • 重写文件全部内容 - UTF-8
  1. // 如果 D:/abc.txt 不存在,则创建它
  2. String txt = Files.write("D:/abc.txt", "some text");
  3. 或者
  4. // 如果 D:/abc.txt 不存在,则什么都不做
  5. String txt = Lang.writeAll(Streams.fileOutw("D:/abc.txt"), content.toString());
  • 获取 Reader - UTF-8
  1. Reander reader = Streams.fileInr("D:/abc.txt");
  2. 或者
  3. Reander reader = Streams.fileInr(new File("D:/abc.txt"));
  • 获取 Writer - UTF-8
  1. Writer writer = Streams.fileOutw("D:/abc.txt");
  2. 或者
  3. Writer writer = Streams.fileOutw(new File("D:/abc.txt"));
  • 获取 InputStream
  1. InputStream ins = Streams.fileIn("D:/abc.txt");
  2. 或者
  3. InputStream ins = Streams.fileIn(new File("D:/abc.txt"));
  • 获取 OutputStream
  1. OutputStream ops = Streams.fileOut("D:/abc.txt");
  2. 或者
  3. OutputStream ops = Streams.fileOut(new File("D:/abc.txt"));

直接在磁盘修改文件属性

  • 将文件移动到新的位置
  1. Files.move(new File("D:/demo/abc.txt"), new File("D:/demo/def.txt"));
  • 将文件改名
  1. Files.rename(new File("D:/demo/abc.txt"), "def.txt");

创建文件对象

  • 将文件后缀改名,从而生成一个新的文件对象。但是并不在磁盘上创建它
  1. return Files.renameSuffix(new File("D:/demo/abc.txt"), ".java");
  • 获取文件主名
  1. assertEquals("abc", Files.getMajorName(new File("D:/demo/abc.txt")));
  • 获取文件后缀名
  1. assertEquals("txt", Files.getSuffixName(new File("D:/demo/abc.txt")));

秒表

  1. Stopwatch sw = Stopwatch.begin();
  2. ...
  3. 这里是你的运行代码
  4. ...
  5. sw.stop();
  6. System.out.println(sw.getDuration());

随机数据

  • 随机字符串
  1. // 生成 100 个长度不超过20的字符串
  2. StringGenerator sg = new StringGenerator(20);
  3. for(int i=0;i<100;i++)
  4. System.out.println(sg.next());
  • 闭区间随机数
  1. return R.random(3,5)
  • 随机枚举值
  1. return (new EnumRandom<MyEnums>(){}).next();
  • 数组不重复随机对象
  1. Random<String> r = new ArrayRandom<String>(Lang.array("A", "B", "C"));
  2. int i = 0;
  3. while (null != r.next()) {
  4. i++;
  5. }
  6. assertEquals(3, i);
  • 数组无穷随机对象
  1. Random<String> r = new RecurArrayRandom<String>(Lang.array("A", "B", "C"));
  2. for(int i=0; i<100; i++)
  3. System.out.println(r.next());

其他

  • 打印 java.util.regex.Matcher 的详细信息
  1. System.out.println(Dumps.matcher(matcher));
  • 解析 Boolean
  1. assertTrue(Lang.parseBoolean("on"));
  2. assertTrue(Lang.parseBoolean("1"));
  3. assertTrue(Lang.parseBoolean("yes"));

本页面的文字允许在知识共享 署名-相同方式共享 3.0协议GNU自由文档许可证下修改和再使用。

原文: http://nutzam.com/core/lang/lang.html