2015年1月

数字点阵的动画实现

预览

未标题-1.gif

原理

数字0的js数组点阵,7x5个 span 元素拼出一个数字出来,同样的方法实现 1-9 的数字

动画效果使用 css3 的 keyframes 实现

[
    [0, 1, 1, 1, 0],
    [1, 1, 0, 1, 1],
    [1, 1, 0, 1, 1],
    [1, 1, 0, 1, 1],
    [1, 1, 0, 1, 1],
    [1, 1, 0, 1, 1],
    [0, 1, 1, 1, 0]
]

QQ20150119-1.png

源码

numb.zip

java Integer中highestOneBit和bitCount的实现原理

highestOneBit

图中的黑色位都可以不关注,然后基本原理就是这样的 (以8位作为例子)

QQ20150110-1.png

bitCount

0x55555555
    01010101010101010101010101010101
0x33333333
    00110011001100110011001100110011
0xf0f0f0f
    00001111000011110000111100001111
0x3f
    00000000000000000000000000111111

QQ20150110-2.png

chrome插件开发杂记

刷新当前 tab 页的3中方式

// 1. 通过在页面中执行js代码
chrome.tabs.getSelected(null, function(tab) {
    var code = 'window.location.reload();';
    chrome.tabs.executeScript(tab.id, {code: code});
});
// 2. 通过chrome的api更新tab的url
chrome.tabs.update(null, {url: url});
// 3. 通过chrome的api刷新
chrome.tabs.reload();

popup 和 background 之间的通讯

以修改 cookie 为例子:

popup:                            -> 修改cookie                          -> 更新UI
background: -> 监听cookie的修改事件               -> 触发监听,与 popup 通讯
// 在background中
chrome.cookies.onChanged.addListener(function (changeInfo) {
    var cookie = changeInfo.cookie;
    if (cookie.domain == 'tool.lu' && cookie.name == 'X-Backend-Server') {
        chrome.runtime.sendMessage({event: "cookie", data: cookie.value}, function (response) {
            // ...
        });
    }
});
// 在popup中
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    // do things
});

popup弹出时候,更新popup的UI

// 在popup中绑定 window.onload 事件
window.onload = init;

background中获取当前加载页面的网页头信息

chrome.webRequest.onHeadersReceived.addListener(function (o) {
    // 判断是否是主页面, 因为页面中可能包含 iframe, image, css, js 等其他资源的加载
    if (o.frameId != 0 || o.type != "main_frame") {
        return;
    }
    for (var i in o.responseHeaders) {
        var header = o.responseHeaders[i];
        console.log(header.name, header.value);
    }
}, {
    "urls":["http://tool.lu/*"]
}, ["responseHeaders"]);

background在页面加载完成之后触发事件

chrome.webNavigation.onCompleted.addListener(function(o) {
    if (o.frameId == 0) {
        // do something...
    }
}, {
    url: [
        {hostContains: 'tool.lu'}
    ]
});

java杂记

效率

先来个 Apache Commons 里面没有的

xiaozi/java-helpers

/*
[
    {id: 1, name: "name1", gender: 1},
    {id: 2, name: "name2", gender: 1},
    {id: 3, name: "name1", gender: 2},
]
*/

/*
[1, 2]
*/
CollectionUtils.pluck(persons, "id", new ArrayList<Integer>())

/*
{
    1: [
        {id: 1, name: "name1", gender: 1},
        {id: 2, name: "name2", gender: 1},
    ],
    2: [
        {id: 3, name: "name1", gender: 2},
    ]
}
*/
CollectionUtils.groupBy(persons, "gender", Integer.class)

/*
去重
*/
CollectionUtils.unique(integers, new ArrayList<Integer>())

Apache Commons 里面的

StringUtils

StringUtils.html

StringUtils.isEmpty(); // null 和 空字符串
StringUtils.isBlank(); // null 和 空字符串 和 全空白字符串
StringUtils.trim(); // 截取掉字符串两侧的空格
StringUtils.strip(); // 截取掉字符串两侧的空白字符串
StringUtils.equalsIgnoreCase(); // 忽略大小写的比较
StringUtils.indexOf(); // 字符/字符串在指定字符串中第一次出现的位置
StringUtils.indexOfIgnoreCase();
StringUtils.lastIndexOf();
StringUtils.contains(); // 是否包含子符串
StringUtils.left();
StringUtils.right();
StringUtils.mid(); // 截取字符串
StringUtils.split(); // 分割字符串
StringUtils.join(); // join数组为字符串
StringUtils.repeat(); // 重复输出字符串
StringUtils.leftPad();
StringUtils.rightPad(); // 填充字符串
StringUtils.lowerCase();
StringUtils.upperCase();
StringUtils.capitalize(); // 大写首字母
StringUtils.reverse(); // 倒转字符串

额,大多数提供的都跟PHP里面一样

CollectionUtils

CollectionUtils.html

CollectionUtils.union(); // 并集
CollectionUtils.intersection(); // 交集
CollectionUtils.containsAny(); // 是否存在交集
CollectionUtils.disjunction(); // 交集的补集
CollectionUtils.subtract(); // 差集
CollectionUtils.filter(); // 过滤

空List的返回

// new ArrayList<>();
Collections.emptyList();

片段

检测端口可用,(绑定,并关掉),来自 Canal

public static boolean isAvailablePort(int port) {
    ServerSocket ss = null;
    try {
        ss = new ServerSocket(port);
        ss.bind(null);
        return true;
    } catch (IOException e) {
        return false;
    } finally {
        if (ss != null) {
            try {
                ss.close();
            } catch (IOException e) {
            }
        }
    }
}

利用字符串标记,优雅解决内外配置文件的加载

// ...
private static final String CLASSPATH_URL_PREFIX = "classpath:";
// ...
    String conf = System.getProperty("canal.conf", "classpath:canal.properties");
    Properties properties = new Properties();
    if (conf.startsWith(CLASSPATH_URL_PREFIX)) {
        conf = StringUtils.substringAfter(conf, CLASSPATH_URL_PREFIX);
        properties.load(CanalLauncher.class.getClassLoader().getResourceAsStream(conf));
    } else {
        properties.load(new FileInputStream(conf));
    }