从本篇开始我们讲述Collections中的一些算法的源代码!本篇主要讲述与排序相关的一些方法,如:排序、反序、反序比较器、乱序、最大值和最小值等。

一、头及一些与算法相关的属性

package java.util;

import java.io.Serializable;

import java.io.ObjectOutputStream;

import java.io.IOException;

import java.lang.reflect.Array;

public class Collections {

private Collections() {    }                           //私有构造器,表明是一个工具类

// 算法相关的成员变量,它们的名字都有一个_THRESHOLD表示它是一个门槛

//当集合中的数据大于此门槛时,选择某个算法,而小于此门槛时选择另外一种算法

//记住它的意义,以及为什么使用即可。

private static final int BINARYSEARCH_THRESHOLD   = 5000;

private static final int REVERSE_THRESHOLD        =   18;

private static final int SHUFFLE_THRESHOLD        =    5;

private static final int FILL_THRESHOLD           =   25;

private static final int ROTATE_THRESHOLD         =  100;

private static final int COPY_THRESHOLD           =   10;

private static final int REPLACEALL_THRESHOLD     =   11;

private static final int INDEXOFSUBLIST_THRESHOLD =   35;

二、排序

Java中的排序主要在Arrays类中,我们的Collections中的排序是将当前List通过Collection提供的toArray作为桥梁转变为Array,然后使用Arrays的排序方法!这就是两者排序的联系!

2.1使用默认的比较器排序

//排序在程序设计过程中经常用到!

//Java集合框架,在Arrays类中提供了各种不同类型数组的排序算法

//Arrays类中的排序,效率很高。请阅读Arrays的源代码

public static <T extends Comparable<? super T>> void sort(List<T> list) {

Object[] a = list.toArray();                                  //将集合转变为数组

Arrays.sort(a);                                                   //运用数组的排序方法排序,采用二分发排序

ListIterator<T> i = list.listIterator();            //这里不可以使用Collection的iterator方法,没有set方法

for (int j=0; j<a.length; j++) {                     //主要使用ListIterator接口的set方法

i.next();

i.set((T)a[j]);                                              //排好叙的数组依次赋给集合元素

}

}

2.2 使用自定义的比较器排序

//关键在Arrays中如何使用比较器的,有机会再讲!你完全可以自己阅读!

public static <T> void sort(List<T> list, Comparator<? super T> c) {    //使用自定义的比较器排序

Object[] a = list.toArray();

Arrays.sort(a, (Comparator)c);                                  //c就是我们自定义的比较器

//调用数组二分发排序方法,通过比较起比较各元素

ListIterator i = list.listIterator();

for (int j=0; j<a.length; j++) {

i.next();

i.set(a[j]);

}

}

三、反序比较器

//在sort和max、min方法中我们看到使用默认比较方法和自定义比较器的完成上面功能的过程!

//在上一篇的例子中也自己写了两个自定义的比较器!可能你还是不太明白,请暂时放放吧!

//在这里会讲述一个特殊的比较器!将默认的比较方法反向,和将自定义的比较器反序

//这就是反向比较器。

public static <T> Comparator<T> reverseOrder() {

//在Coolections中调用这个静态的方法,创建一个比较器

return (Comparator<T>) REVERSE_ORDER;                           //返回一个对象

}

private static final Comparator REVERSE_ORDER = new ReverseComparator();

//这个对象是所有反序比较器共有的!Flighweight的应用

private static class ReverseComparator<T>    implements Comparator<Comparable<Object>>, Serializable {

private static final long serialVersionUID = 7207038068494060240L;

public int compare(Comparable<Object> c1, Comparable<Object> c2) {

return c2.compareTo(c1);                        //这是该比较器的主要方法,调换原先的比较次序

}

}

public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) {              //使用自定义比较器的反序比较器

if (cmp == null)    return new ReverseComparator();  // Unchecked warning!!

return new ReverseComparator2<T>(cmp);

}

private static class ReverseComparator2<T> implements Comparator<T>, Serializable {

private static final long serialVersionUID = 4374092139857L;

private Comparator<T> cmp;

ReverseComparator2(Comparator<T> cmp) {

assert cmp != null;

this.cmp = cmp;

}

public int compare(T t1, T t2) {

return cmp.compare(t2, t1);                                        //调换原先比较器的比较次序

}

}

到目前为止我们排序的方法比较多了!以下是几种排序及其注意点:

1.        首先这些加入集合List中的元素,必须实现Comparable接口,实现其方法compareTo(Object)方法;

2.        我们可以使用默认的比较方法排序,Collections.sort(List);

3.        我们可以使用默认比较器的反序比较器,Collections.sort(List, Collections.
reverseOrder());能明白吧!他也是一个比较器,只是是一个特殊的比较器!领会吧!

4.        我们可以采用自定义的比较器,象我们上篇讲的两个年龄的比较器和姓名的比较器;Collections.sort(List,MyComparator)。

5.        我们可以在有了一个自定义的比较器时,对器排序不是很满意,想反向一下!这时也可以使用方向比较器;Collections.sort(List, Collections.
reverseOrder(MyComparator))。我现在告诉你这也是一个装饰器模式你能理解吗??ReverseComparator2是不是啊!理解理解Decorator模式的场景,意图看看!还是要告诉你模式是一种观念,不是一成不变的,领会吧!在必要的时候使用他!

四、最小值

求最大值、最小值很常见吧!我在《由一个简单的程序谈起》中建立的那个小程序,使用了上面的sort方法,然后取出最后一个对象,其实就是一个求最大值的过程。不过Collections为我们提供了两种求最值的方法哦!

6.1使用对象默认的比较器求最小值

//求最小值的思路是:刚开始取第一个元素作为最小值,然后依次遍列,

//有比他小的就替换当前这个最小值,直到所有的遍列完成,

//那个最终的最小值就是整个List的最小值

//唉!Who
laughs last,wo laughs better!

//使用下一个对象的compateTo方法与当前对象比较

public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {

Iterator<? extends T> i = coll.iterator();                                //得到集合的遍历器!不懂就查看遍历器模式吧!

T candidate = i.next();                                                          //取出第一个元素与其它元素比较!为什么?

while(i.hasNext()) {

T next = i.next();

if (next.compareTo(candidate) < 0)                            candidate = next;

//使用默认的比较方法!具体怎么用,见前一篇文章!

}

return candidate;

}

6.2 使用自定义的比较器求最小值

public static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp) {

if (comp==null)        return (T)min((Collection<SelfComparable>) (Collection) coll);

//上面一句的意思是:没有比较器使用自身的比较方法!当然调用上面的方法哦!

Iterator<? extends T> i = coll.iterator();

T candidate = i.next();

while(i.hasNext()) {

T next = i.next();

if (comp.compare(next, candidate) < 0)  candidate = next;

//两者的差别看到了吧!使用默认的比较方法用next.compareTo(candidate)
< 0

//看仔细了!所有的细节都在这里

}

return candidate;

}

private interface SelfComparable extends Comparable<SelfComparable> {}                   // 辅助的接口而已

求最小值的思路我们可以明显看出使用自身的比较器和自定义比较器的差别了!你仔细都这两个方法吧!

五、最大值

//和求最小值同样的思路,我就不罗嗦了!

10.1使用对象默认的比较器求最大值

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {

Iterator<? extends T> i = coll.iterator();

T candidate = i.next();

while(i.hasNext()) {

T next = i.next();

if (next.compareTo(candidate) > 0)

candidate = next;

}

return candidate;

}

10.2使用自定义的比较器求最大值

public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {

if (comp==null)       return (T)max((Collection<SelfComparable>) (Collection) coll);

Iterator<? extends T> i = coll.iterator();

T candidate = i.next();

while(i.hasNext()) {

T next = i.next();

if (comp.compare(next, candidate) > 0)

candidate = next;

}

return candidate;

}

//补充一下哦!其实在Collections中当你对这个List排序后,求最值也不需要这么麻烦,

//你得到排序后List的最后一个和最前面一个不就是最大值和最小值吗!

//仅仅要得到最大值和最小值,建议使用这个方法!为什么啊?

//两者性能相差不少。我们这个方法只要遍列一次,比较一次!

//先排序然后在得到最值有以下几个步骤:遍列一次得到一个数组,数组遍列且比较一次

//得到一个排序好的数组,再遍列一次插入List,几倍的差距吧!

//凡是多动脑!Use your head , and
you’ll find a way !

六、反序

//将List中的元素的次序完全反过来!

public static void reverse(List<?> list) {

int size = list.size();

if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {

//根据元素的个数和List的类型决定使用何种交换次序的策略

for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)              //从第一个开始依次交换头和对应尾的持续

swap(list, i, j);                                                              //交换index为i和j的元素

} else {

ListIterator fwd = list.listIterator();

ListIterator rev = list.listIterator(size);

for (int i=0, mid=list.size()>>1; i<mid; i++) {                        //一共移动元素个数的1/2

Object tmp = fwd.next();                                              //得到前端的第i个元素

fwd.set(rev.previous());                                              //将前端i的元素设置为第size-i个元素

rev.set(tmp);                                                                //将后端size-i的元素设置为第i个元素

}

}                                                                                                     //简单吧!

}

//这个反序与排序的反序又有较大的差别!自己研究吧!

七、乱序

//经常用的变态的方法哦!使用循环向List中插入和循环变量一致的Integer对象这是网络上的例子

//然后给你讲其它的!变态吧!本来有次序的,乱序一下,再给你写个自定义的排序器排序一下!

public static void shuffle(List<?> list) {                                                     //将List中的元素打乱次序

shuffle(list, r);                                                                                  //使用一个随机发生器

}

private static Random r = new Random();                                             //随机发生器

public static void shuffle(List<?> list, Random rnd) {                     //乱序的核心方法

int size = list.size();

if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {        //根据门槛条件及类型选择策略

for (int i=size; i>1; i--)                                                                    //将第i个元素和其它任何元素反序

swap(list, i-1, rnd.nextInt(i));

} else {

Object arr[] = list.toArray();                                                            //对象太多转变为数组处理

for (int i=size; i>1; i--)

swap(arr, i-1, rnd.nextInt(i));

ListIterator it = list.listIterator();

for (int i=0; i<arr.length; i++) {                                                        //将乱序后的数组的值依次插入List中

it.next();

it.set(arr[i]);

}

}

}

public static void swap(List<?> list, int i, int j) {                                        //将List中的第i和j的元素换序

final List l = list;

l.set(i, l.set(j, l.get(i)));                                                                              //这个明白吧!List接口的基本方法

}

private static void swap(Object[] arr, int i, int j) {                                      //将数组的i和j的元素互换次序

Object tmp = arr[i];

arr[i] = arr[j];

arr[j] = tmp;

}

//吃饱了,没事撑着的方法。不过在某些场合还是很有用的!

手头有个清华大学严蔚敏和吴伟民的《数据结构》pascal语言版的!一本经典的数据结构的教程,第十章、第十一章就是排序!第九章就是查找!下面我们就会研究Collections中的查找相关的知识!其实数据结构这们课不要太基础哦!就是一些堆、栈、队列、表、树、图以及一些排序和查找算法!不会这个可能干其它也很不容易!他是你从事IT行业的基础!不信你去问问严老师!这是个基础,在实际项目中,可能要建立很多比这个复杂很多的数据结构!不信啊!JDBC中的ResultSet就极其明显是一个数据结构!多看看吧!

本来今天不想写的,有兄弟在QQ里说:“你写得太慢了,我都看完了!”有压力了我!几天挺累的,可不能让你们的写作枪手崩溃哦!毕竟能写的东西太多太多了!一切才刚刚开始啊!

唉!一转眼,博客已经开了近一个月!这一个月我写了几十篇,有一次看完了Collections Framework的SourceCode,同时看完了IO包中除ObjectIn/OutputStream相关的类!你有干了写这么呢??总结总结吧!每天都有什么收获啊!每个月都有什么收获啊!人吗,总得一天比一天强吧!要不然活着还有什么意义啊!

元旦要到了!我也要放假了!提前祝贺大家:新年好!新年新气象!学习进步!家庭和谐!

今年没好好干的明年可得好好干!没找到工作的学生可以继续找!看看http://www.java-cn.com/上的招聘信息吧!也有不少月薪8k以上的啊!只要你有能耐!钱终究会有的!只有你有那个能力,才可能拿到那个薪水!学好Computer、学好English、学会做人――做个素质、有良心的人!

本篇讲述查找相关的内容!这里的查找和List、Set、Map他们具体实现的查找是有差别的,一般还是建议使用对象自身的查找!

八、查找

8.1使用对象默认的比较器查找

//比较器的原理在上面两篇已经讲过了!这里不重叙了!

//从List中查找指定对象的位置

public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {

if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)

//个数小于5000,或者为随机存取的List使用“二分发”查找

//看看我前面的FailFast机制的文章查查list有几种类型,有差别吗???

return Collections.indexedBinarySearch(list, key);                                //见下面方法

else            //否则使用遍历器查找,效率较低,原因见下面

return Collections.iteratorBinarySearch(list, key);

}

//经典的二分发查找,注意查找前必须已经排序完成。

private static <T> int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {

int low = 0;                                                                                                               //低位索引,最小

int high = list.size()-1;                                                                                  //高位索引,最大

while (low <= high) {

int mid = (low + high) >> 1;                                                                         //两者位置的中间

Comparable<? super T> midVal = list.get(mid);                                    //得到中间位置的值

int cmp = midVal.compareTo(key);                     //将要查找的对象与中间值比较

if (cmp < 0)

low = mid + 1;                                                 //要查找的值小于中间值,在下半段比较

else if (cmp > 0)

high = mid - 1;                                                 //要查找的值小于中间值,在上半段比较

else

return mid; // key found                                  //相等就证明已经找到,返回位置

}

return -(low + 1);  // key not found                                //不存在,则返回应该所在位置的相反数

}

private static <T> int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key) {

//根据自定义的比较器查找指定的元素

int low = 0;

int high = list.size()-1;

ListIterator<? extends Comparable<? super T>> i = list.listIterator();

while (low <= high) {

int mid = (low + high) >> 1;                                             //移位完成除以2运算

Comparable<? super T> midVal = get(i, mid);  //从List中得到中间位的值,见后面

int cmp = midVal.compareTo(key);                     //中间位与要查找值的比较

if (cmp < 0)                                                               //分析同上

low = mid + 1;

else if (cmp > 0)

high = mid - 1;

else

return mid; // key found

}

return -(low + 1);  // key not found

}

//该方法查找中间位置的值效率较低。

//主要是由于:总是通过从当前位置移动游标到中间位置。

private static <T> T get(ListIterator<? extends T> i, int index) {

T obj = null;

int pos = i.nextIndex();                         //当前游标的位置

if (pos <= index) {                                  //当前位置在中间以下,则向后遍历

do {

obj = i.next();

} while (pos++ < index);

} else {                                                     //当前位置在中间以上,则向前遍历

do {

obj = i.previous();

} while (--pos > index);

}

return obj;

}

8.2使用自定义的比较器查找

//这种查找方法可能对一般的朋友比较陌生

public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c) {

if (c==null)         return binarySearch((List) list, key);

if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)

return Collections.indexedBinarySearch(list, key, c);

else

return Collections.iteratorBinarySearch(list, key, c);

}

private static <T> int indexedBinarySearch(List<? extends T> l, T key, Comparator<? super T> c) {

int low = 0;

int high = l.size()-1;

while (low <= high) {

int mid = (low + high) >> 1;

T midVal = l.get(mid);

int cmp = c.compare(midVal, key);                                         //整个比较方法就这个地方有差别

if (cmp < 0)

low = mid + 1;

else if (cmp > 0)

high = mid - 1;

else

return mid; // key found

}

return -(low + 1);  // key not found

}

private static <T> int iteratorBinarySearch(List<? extends T> l, T key, Comparator<? super T> c) {

int low = 0;

int high = l.size()-1;

ListIterator<? extends T> i = l.listIterator();

while (low <= high) {

int mid = (low + high) >> 1;

T midVal = get(i, mid);

int cmp = c.compare(midVal, key);                                         //同上,唯一的差别

if (cmp < 0)

low = mid + 1;

else if (cmp > 0)

high = mid - 1;

else

return mid;                                                                        // 找到对于的值,则返回该值

}

return -(low + 1);                                                                                //没有则返回该值应该位置的相反数

}

九、位置查找

//在整个Java
Collections Framework中只有List之类的对象对外界是暴露位置的,

//位置实际上就是索引,对应于数组的下标!!!

//不过我们下面这个位置查找不同!

9.1第一次出现的位置

//该方法查找某个List在另外一个List中的位置

public static int indexOfSubList(List<?> source, List<?> target) {

int sourceSize = source.size();

int targetSize = target.size();

int maxCandidate = sourceSize - targetSize;                       //最多查找差值的次数!!!

if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||

(source instanceof RandomAccess&&target instanceof RandomAccess)) {

nextCand:

for (int candidate = 0; candidate <= maxCandidate; candidate++) {                    //查找次数循环

for (int i=0, j=candidate; i<targetSize; i++, j++)                     //每个对于位置元素是否相等

if (!eq(target.get(i), source.get(j)))

continue nextCand;  // Element mismatch, try next cand

return candidate;  // All elements of candidate matched target

}

} else {  // Iterator version of above algorithm

ListIterator<?> si = source.listIterator();

nextCand:

for (int candidate = 0; candidate <= maxCandidate; candidate++) {

ListIterator<?> ti = target.listIterator();

for (int i=0; i<targetSize; i++) {

if (!eq(ti.next(), si.next())) {

// Back up source iterator to next candidate

for (int j=0; j<i; j++)

si.previous();

continue nextCand;

}

}

return candidate;

}

}

return -1;  // No candidate matched the target

}

9.2最后的位置

//和上面的方法基本相同,只是从后向前遍列而已

public static int lastIndexOfSubList(List<?> source, List<?> target) {

int sourceSize = source.size();

int targetSize = target.size();

int maxCandidate = sourceSize - targetSize;

if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||

source instanceof RandomAccess) {   // Index access version

nextCand:

for (int candidate = maxCandidate; candidate >= 0; candidate--) {

for (int i=0, j=candidate; i<targetSize; i++, j++)

if (!eq(target.get(i), source.get(j)))

continue nextCand;  // Element mismatch, try next cand

return candidate;  // All elements of candidate matched target

}

} else {  // Iterator version of above algorithm

if (maxCandidate < 0)

return -1;

ListIterator<?> si = source.listIterator(maxCandidate);

nextCand:

for (int candidate = maxCandidate; candidate >= 0; candidate--) {

ListIterator<?> ti = target.listIterator();

for (int i=0; i<targetSize; i++) {

if (!eq(ti.next(), si.next())) {

if (candidate != 0) {

// Back up source iterator to next candidate

for (int j=0; j<=i+1; j++)

si.previous();

}

continue nextCand;

}

}

return candidate;

}

}

return -1;  // No candidate matched the target

}

十、频繁

//查找某个对象在Collection中出现的次数,极其简单的方法

public static int frequency(Collection<?> c, Object o) {

int result = 0;

if (o == null) {

for (Object e : c)

if (e == null)     result++;

} else {

for (Object e : c)

if (o.equals(e))     result++;

}

return result;

}

十一、查找取代

//查找某个对象,用其它对象取代他,所有的这种对象对会被取代

public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) {

boolean result = false;

int size = list.size();

if (size < REPLACEALL_THRESHOLD || list instanceof RandomAccess) {

if (oldVal==null) {

for (int i=0; i<size; i++) {

if (list.get(i)==null) {

list.set(i, newVal);

result = true;

}

}

} else {

for (int i=0; i<size; i++) {

if (oldVal.equals(list.get(i))) {

list.set(i, newVal);

result = true;

}

}

}

} else {

ListIterator<T> itr=list.listIterator();

if (oldVal==null) {

for (int i=0; i<size; i++) {

if (itr.next()==null) {

itr.set(newVal);

result = true;

}

}

} else {

for (int i=0; i<size; i++) {

if (oldVal.equals(itr.next())) {

itr.set(newVal);

result = true;

}

}

}

}

return result;

}

又一篇结束了!好像快了点!不过这个系列的文章我酝酿好久了!有收获吧!这个系列一共10篇左右!下一个系列是IO至少10篇!我加油写,你加油看哦!谢谢支持!

Collections Framework中的算法(之二)的更多相关文章

  1. Java Collections Framework

    集合OR 容器 通常我们会用数组去保存一些基本数据类型,数组是编译器支持的类型,但是数组的一个明显缺点就是具有固定尺寸,而在一般情况下,只有在程序运行的时候,我们才能知道要保存的具体数目. Java类 ...

  2. (二)一起学 Java Collections Framework 源码之 AbstractCollection

    . . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述(未完成) (二)一起学 Java Collections Framework 源码之 Abs ...

  3. (一)一起学 Java Collections Framework 源码之 概述

    . . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述 JDK 中很多类 LZ 已经使用了无数次,但认认真真从源码级研究过其原理的还只占少数,虽然从 ...

  4. 算法(二)之遗传算法(SGA)

    算法(二)之遗传算法(SGA) 遗传算法(Genetic Algorithm)又叫基因进化算法或进化算法,是模拟达尔文的遗传选择和自然淘汰的生物进化过程的计算模型,属于启发式搜索算法一种. 下面通过下 ...

  5. 【JAVA集合框架一 】java集合框架官方介绍 Collections Framework Overview 集合框架总览 翻译 javase8 集合官方文档中文版

    原文链接: https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html 原文内容也一并附加在本文最 ...

  6. Java Collections Framework概览

    本文github地址 概览 容器,就是可以容纳其他Java对象的对象.Java Collections Framework(JCF)为Java开发者提供了通用的容器,其始于JDK 1.2,优点是: 降 ...

  7. Java Collections Framework Java集合框架概览

    Java SE documents -- The Collections Framework http://docs.oracle.com/javase/8/docs/technotes/guides ...

  8. C#中的线程(二)线程同步

    C#中的线程(二)线程同步   Keywords:C# 线程Source:http://www.albahari.com/threading/Author: Joe AlbahariTranslato ...

  9. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework中的spring web MVC模块

    spring framework中的spring web MVC模块 1.概述 spring web mvc是spring框架中的一个模块 spring web mvc实现了web的MVC架构模式,可 ...

  10. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->关于spring framework中的beans

    Spring framework中的beans 1.概述 bean其实就是各个类实例化后的对象,即objects spring framework的IOC容器所管理的基本单元就是bean spring ...

随机推荐

  1. 【YashanDB知识库】账号被锁,如何分析具体原因

    问题现象 客户刚开始使用YashanDB的时候,经常收到客户反馈账号被锁,但是不知道哪里触发了. 问题的风险及影响 客户环境为测试环境,影响测试业务的开展. 问题影响的版本 YashanDB版本:23 ...

  2. 题解:AT_arc116_b [ARC116B] Products of Min-Max

    在题库里面乱翻,就翻到了. 因为在这道题里面子序列不需要考虑元素顺序,所以原序列无论是什么顺序都不会影响答案. 所以先把元素按照从大到小的顺序排列,然后考虑每个元素的贡献. 在当前序列中,对于元素 \ ...

  3. 论文解读 -TongGu:专注于文言文的大模型

    一.简要介绍 文言文是通往中国古代丰富遗产和智慧的门户,但其复杂性给大多数没有专业知识的现代人构成了巨大的理解障碍.虽然大型语言模型(LLM)在自然语言处理(NLP)方面显示出了显著的能力,但它们在文 ...

  4. DOM – IntersectionObserver

    介绍 IntersectionObserver 的作用是监听某个元素是否出现在框内 (比如 viewport). 它可以实现 lazy load image, 一开始图片是没有加载的, 当图片出现在 ...

  5. Maven 依赖项管理&&依赖范围

    依赖管理   使用坐标导入jar包     1.在pom.xml 中编写 <dependencies> 标签     2.在 <dependencies> 标签中使用 < ...

  6. Listener——监听器

    Listener   

  7. 音视频入门-2-ffmpeg-Linux下编译浅析,推流拉流快速体验

      下载ffmpeg http://ffmpeg.org/download.html 1 .2 两种方式可以下载, 皆可. 编译ffmpeg ./configure -prefix=/usr/loca ...

  8. T2 的莫反式子

    正在实现,不知道对不对,但是先放这,哪个大佬发现问题了和我说下 设 \[f(l)=\sum\cdots\sum[\gcd=1,\text{lcm}=l] \] \[g(l)=\sum\cdots\su ...

  9. golang的类型转换

    今天我们来说说一个大家每天都在做但很少深入思考的操作--类型转换. 本文索引 一行奇怪的代码 go的类型转换 数值类型之间互相转换 unsafe相关的转换 字符串到byte和rune切片的转换 sli ...

  10. Android dex、odex、oat、vdex、art区别

    1.dex java程序编译成class后,dx工具将所有class文件合成一个dex文件,dex文件是jar文件大小的50%左右. 2.odex(Android5.0之前)全称:Optimized ...