• 1 TreeSet简介

  • 2 基本用法与特点

  • 3 制定单值比较规则

    • 3.1 自然排序(compareTo(Object obj))

    • 3.2 定制排序(定义比较器类)

      • 3.2.1 普通类内定义

      • 3.2.2 单例类定义(更常用)

      • 3.2.3 String的中文排序

  • 4 多个比较规则时的情况

  • 5 增删改查需要注意

    • 5.1 当比较方法的返回值无法得到0

    • 5.2 遍历增删元素时

  • 6 单值类型集合总结

    • 6.1 Collection(单值类型统一的父接口)

    • 6.2 List(有序,不唯一)

    • 6.3 Set(无序,唯一)

    • 6.4 SortedSet(有序,唯一)

    • 6.5 所有单值集合都有的方法

1 TreeSet简介

作为SortedSet接口的一个实现类,特点是有序、存储元素唯一的。底层实现的数据结构为二叉树。这里的二叉树是自平衡二叉树,集合里面的根元素,一日是根,不代表永远是根,底层会自动的进行旋转修复。

2 基本用法与特点

  • 创建一个TreeSet集合对象(暂用两种方式)
           与前面学到的集合相同,TreeSet集合对象创建也依据不同的版本有不同的方法。参照前面的两篇文章。
           但在TreeSet类中,依据传入的不同参数,初始化实现的构造方法也不同。HashSet使用其创建初始空间和加载因子,这里根据传入的参数定义比较规则。重点说其中两种构造方法。

      TreeSet()构造一个新的空TreeSet,该TreeSet根据其元素的自然顺序进行排序。 TreeSet(Comparator<? super E> comparator) 构造一个新的空TreeSet,它根据指定比较器进行排序。
    
  • 添加元素到TreeSet

      set.add(Object obj);Collections.addAll(set, Object obj1,Object obj2....);set1.addAll(集合类型的引用);
    
  • 得到TreeSet集合的大小

      set.size();
    
  • 判断集合里是否包含指定元素

      set.contains(Object obj);
    
  • 指定元素进行删除

      set.remove(Object obj);
    

注意,TreeSet中的删除、判断是否包含指定元素底层依赖的依据是实现接口Comparable中的compareTo(),当方法返回为0,即相当于equals()返回的true。

与HashSet不同,TreeSet插入元素时的判断标准其实只需实现Comparable接口的compareTo()方法就可以。不需重写equals()和hashCode()方法。这个方法返回值不能为0,依赖compareTo操作集合的方法均不得使用。需要遍历获取值进行判断是否存在或者删除。

  • 得到集合里的第一个元素并且删除(poll:投出)

      set.pollFirst()
    
  • 得到集合里最后一个元素并且删除

      set.pollLast();
    
  • 得到集合里的第一个元素

      set.first()
    
  • 得到集合里最后一个元素

      set.last();
    
  • 遍历

      //遍历//foreachfor(Integer x : set){System.out.println(x);}//迭代器for(Iterator<Integer> i = set.iterator(); i.hasNext(); ){Integer num = i.next();System.out.println(num);}
    

    与前面HashSet一样,因为HashSet集合是无序的,在遍历时不能根据for + 下标进行顺序遍历,只能根据迭代器进行遍历。foreach底层也是依据迭代器遍历。另外TreeSet也缺少依据下标的get()和remove()。

    • 倒序输出

      TreeSet<E>  reSet = (TreeSet)set.descendingSet();
      
  • 例题:

//将TreeSet中的元素倒序输出
import java.util.*;
public class Example{public static void main(String[] args){TreeSet<Integer> set = new TreeSet<>();Collections.addAll(set,50,80,70,40,25,88);System.out.println(set);//--->[25, 40, 50, 70, 80, 88]ArrayList<Integer> list = new ArrayList<>();while(set.size() != 0){//获取最后一个元素并且删除list.add(set.pollLast());}System.out.println(list);//--->[88, 80, 70, 50, 40, 25]}
}

因TreeSet同样是无序的,所以它也不具有以下标为参数列表的方法,与HashSet相同。

3 制定单值比较规则

3.1 自然排序(compareTo(Object obj))

//依照球号从小到大排序(基本数据类型)
import java.util.*;
public class Test1{public static void main(String[] args){TreeSet<Ball> set = new TreeSet<>();Ball b1 = new Ball(3,'红');Ball b2 = new Ball(5,'蓝');Ball b3 = new Ball(1,'黄');Collections.addAll(set,b1,b2,b3);System.out.println(set);//--->[1号球:黄,3号球:红色,5号球:蓝色]}
}//需实现Comparable<泛型>类中的int compareTo(泛型)方法
class Ball implements Comparable<Ball>{int number;char color;public Ball(int number,char color){this.number = number;this.color = color;}@Overridepublic int compareTo(Ball b){//新元素(调用):this.number//旧元素(传入):b.numberreturn this.number - b.number;}@Overridepublic String toString(){return number + "号球:" + color + "色";}
}
//按名字升序排序(引用数据类型)
import java.util.*;
public class Test2{public static void main(String[] args){TreeSet<Student> set = new TreeSet<>();Student stu1 = new Student("Bob",30);Student stu2 = new Student("Cindy",18);Student stu3 = new Student("Ella",18);Student stu4 = new Student("Zella",18);Collections.addAll(set,stu1,stu2, stu3, stu4);System.out.println(set);//--->[Bob:30, Cindy:18, Ella:18, Zella:18]}
}class Student implements Comparable<Student>{String name;int age;public Student(String name,int age){this.name = name;this.age = age;}@Overridepublic String toString(){return name + ":" + age;}@Overridepublic int compareTo(Student stu){return this.name.compareTo(stu.name);}
}

当compareTo方法返回0时,不存储;当compareTo方法返回正数时,存入二叉树的右子树;当compareTo方法返回负数时,存入二叉树的左子树。

  • 新元素(调用):this . xxx

  • 旧元素(传入):obj . xxx

  • 升序:

    • 基本数据类型:返回“新元素 - 旧元素”,当值为正,将新(较大的)元素右置
    • 引用数据类型:新元素.compareTo(旧元素)
  • 降序:

    • 基本数据类型:返回“旧元素 - 新元素”,当值为正,将新(较小的)元素右置
    • 引用数据类型:旧元素.compareTo(新元素)

3.2 定制排序(定义比较器类)

3.2.1 普通类内定义

//按名字升序排序
import java.util.*;
public class Test{public static void main(String[] args){MyComparator mc = new MyComparator();TreeSet<Student> set = new TreeSet<>(mc);Student stu1 = new Student("Bob",30);Student stu2 = new Student("Cindy",18);Student stu3 = new Student("Ella",18);Student stu4 = new Student("Zella",18);Collections.addAll(set,stu1,stu2, stu3, stu4);System.out.println(set);//--->[Bob:30, Cindy:18, Ella:18, Zella:18]}
}class Student{String name;int age;public Student(String name,int age){this.name = name;this.age = age;}@Overridepublic String toString(){return name + ":" + age;}
}class MyComparator implements Comparator<Student>{//参数列表传入的方式:(新元素, 旧元素)@Overridepublic int compare(Student s1, Student s2){return s1.compareTo(s2);}
}
  • 新元素(调用):compare()参数列表中第一个参数

  • 旧元素(传入):compare()参数列表中第二个参数

  • 升序:

    • 新元素.compareTo(旧元素)
  • 降序:

    • 旧元素.compareTo(新元素)

3.2.2 单例类定义(更常用)

注意单例时实现的类和方法与类内定义的都不一样

//按名字升序排序(单例定义)
import java.util.*;
public class TestSingleTask{public static void main(String[] args){TreeSet<Student> set = new TreeSet<>(MyComparator.getMyComparator());Student stu1 = new Student("Bob",30);Student stu2 = new Student("Cindy",18);Student stu3 = new Student("Ella",18);Student stu4 = new Student("Zella",18);Collections.addAll(set,stu1,stu2, stu3, stu4);System.out.println(set);//--->[Bob:30, Cindy:18, Ella:18, Zella:18]}
}class Student{String name;int age;public Student(String name,int age){this.name = name;this.age = age;}@Overridepublic String toString(){return name + ":" + age;}
}class MyComparator implements Comparator<Student>{//私有化构造方法private MyComparator(){}//私有并静态实现一个本类引用private static MyComparator myComparator = new MyComparator();//供外界调用的get方法public static MyComparator getMyComparator(){return myComparator;}//参数列表传入的方式:(新元素, 旧元素)@Overridepublic int compare(Student s1, Student s2){return s1.compareTo(s2);}
}

3.2.3 String的中文排序

String的compareTo()默认按首字母排序,若要为中文元素排序,需要导入"java.text.*"包使用元素的第一个字的首字母排序,否则直接按照Unicode编码排序。String的中文排序(升序排列):

//首先导包
import java.text*;//定义Collator的引用,并在实例中传入中文Collator instance = Collator.getInstance(Locale.CHINA);//使用引用调用compare方法,参数列表中第一位是新元素,第二位是旧元素return instance.compare(s1.name, s2.name);

若改为降序,将compare()的两个参数调换位置即可。

4 多个比较规则时的情况

想按多个属性综合排序时,优先比较什么属性,就优先描述什么属性不同。其他定义方式与单值相同。不论是定制排序还是自然排序,写法相同,都是根据条件写出if的几个判断以及完全相同的元素是否允许存储(此时返回定值1)。

import java.util.*;
public class Test{/**两个学生优先按照分数进行升序排序如果分数一样的话 按照年龄降序排序如果分数和年龄都一样的话 那么按照姓名升序排序如果所有属性都一样 那么也要存储*/public static void main(String[] args){TreeSet<Student> set = new TreeSet<>();Student s1 = new Student("Andy",20,45);Student s2 = new Student("Lee",22,99);Student s3 = new Student("Andy",20,45);Student s4 = new Student("Jack",18,99);Collections.addAll(set,s1,s2,s3,s4);System.out.println(set);//s1 s3  s2 s4}
}class Student implements Comparable<Student>{String name;int age;int score;public Student(String name,int age,int score){this.name = name;this.age = age;this.score = score;}@Overridepublic String toString(){return name + "[" + age + "," + score + "]";}@Overridepublic int compareTo(Student stu){//新元素Student s1 = this;//老元素Student s2 = stu;/*//分数相等,否则按分数升序排列if(s1.score == s2.score){//年龄相等,否则按年龄降序排列if(s1.age == s2.age){//姓名相同,否则按姓名(英文)首字母升序排列if(s1.name.equals(s2.name)){//若分数、年龄、姓名都一致,返回大于0,新元素在右子树存储return 1;}else{return s1.name.compareTo(s2.name);}}else{return s2.age - s1.age;}}else{return s1.score - s2.score;}*/     //直接考虑对立面的条件,上面的分析可以简化为://按分数升序排列if(s1.score != s2.score) return s1.score - s2.score;//若分数一样,按年龄降序排列if(s1.age != s2.age) return s2.age - s1.age;//若分数、年龄都一样,按姓名(英文)首字母升序排列if(!(s1.name.equals(s2.name))) return s1.name.compareTo(s2.name);//都一样,也要存储记录return 1;}
}

5 增删改查需要注意

5.1 当比较方法的返回值无法得到0

在重写compareTo()时,尽量保证这个方法有机会返回0,否则集合无法保证其元素唯一性,集合也不能调用方法指定元素进行删除(remove(Object obj)),也无法使用集合调用方法查询元素是否包含某个值(contains(Object obj)),无法使用get(Object obj)。(参照对象.compareTo(元素) == 0时,contains才会为true或remove才会删除这个元素)

当compareTo()一定没有机会返回0时,如果想要删除集合里面的某个元素,要使用迭代器的删除方法:迭代器引用.remove(),其底层不遵循compareTo()的比较规则,只与当前光标位置有关,所以可直接删除元素。
要查找元素是否包含某个值时,也要使用迭代器,取出这个元素值之后再进行比对。

如下面的例子:

import java.util.*;
public class Example{public static void main(String[] args){TreeSet<Teacher> set = new TreeSet<>();Teacher tea = new Teacher("Tom",35);set.add(tea);set.add(tea);//底层执行tea.compareTo(tea),返回1,加入右子树set.add(tea);//底层执行tea.compareTo(tea),返回1,加入右子树/**执行结果tea[Tom,35]tea[Tom,35]tea[Tom,35]*/set.remove(tea);//参照对象.compareTo(元素) == 0? 等于0就删除System.out.println(set);//--->[Tom:35, Tom:35, Tom:35]for(Iterator<Teacher> car = set.iterator();car.hasNext();){//取出元素进行比对Teacher t = car.next();if(t.name.equals("Tom")){car.remove();}}System.out.println(set);//[]}
}class Teacher implements Comparable<Teacher>{String name;int age;public Teacher(String name,int age){this.name = name;this.age = age;}@Overridepublic String toString(){return name + ":" + age;}@Overridepublic int compareTo(Teacher tea){//所有的新元素都被认为比集合里的旧元素大,新元素置于右子树return 1;}
}

5.2 遍历增删元素时

  • 与之前集合相同,删除元素时使用迭代器的删除方法;增加元素时要使用一个新的TreeSet集合接收元素,并在遍历结束之后使用TreeSet的addAll方法将这个集合添加到原集合中。否则会报CME异常。
import java.util.*;
public class Test{public static void main(String[] args){TreeSet<Integer> set = new TreeSet<>();Collections.addAll(set,45,66,72,38,90,59);//删除集合里面所有不及格的分数for(Iterator<Integer> i = set.iterator();car.hasNext();){Integer score = i.next();if(score < 60){i.remove();}}System.out.println(set);//--->[66,72,90]}
}
  • 与HashSet集合不得直接操作已加入集合的对象中已参与生成哈希特征码的属性类似,修改元素时,不要直接修改已被添加进集合的对象的参与排序(compareTo或compare方法)的属性值。否则将会造成修改后的元素无法删除的问题,且再添加同样的元素,不会被认为是同一个对象。(虽在树的一个节点改变了其属性,节点却不发生移动,使得删除时根据改变之后的路径搜索这个节点无法使结果等于0;且再添加时这个改变后的应该对应的正确节点仍为空,故可以添加)
  • 如果一定要修改,需要先获取对象,删除这个对象后,将对象进行修改后再添加回集合中。
import java.util.*;
public class Test{public static void main(String[] args){TreeSet<Teacher> set = new TreeSet<>();Teacher t1 = new Teacher("Sam",32);Teacher t2 = new Teacher("Andy",23);set.add(t1);set.add(t2);/**t1[Sam,32]t2[Andy,33]*/t2.age += 10;set.remove(t2);//本应该是升序排列,Andy元素在原节点增长了10,没有移动出现混乱System.out.println(set);//--->[Andy:33, Sam:32]set.add(t2);System.out.println(set);//--->[Andy:33, Sam:32, Andy:33]}
}
class Teacher implements Comparable<Teacher>{String name;int age;public Teacher(String name,int age){this.name = name;this.age = age;}@Overridepublic String toString(){return name + ":" + age;}@Overridepublic int compareTo(Teacher tea){return this.age - tea.age;}
}

6 单值类型集合总结

6.1 Collection(单值类型统一的父接口)

  • 父接口:JCF

  • 子接口:List、Set

  • 共有的方法:add()、addAll()、size()、contains(Object obj)、iterator()、remove(Object obj)、clear()、get(Object obj)

  • 都可以使用foreach、迭代器进行循环遍历

  • 共有的特性:
    当使用迭代器遍历集合的过程中,不允许对集合的整体进行添加/删除操作 否则都会触发CME异常,如果一定要遍历的过程中删除的话,使用迭代器的删除方法。若要增加,定义新的集合,遍历时添加,遍历结束后将新的集合addAll进旧集合。

  • 善用contains(Object obj)、remove(Object obj)并设置相关的equals()、hashCode()或compareTo()/compare()来简化代码,但注意remove(Object obj)不能在foreach和迭代器遍历中使用。

6.2 List(有序,不唯一)

  • 父接口:Collection

  • 主要实现类:

    • ArrayList(数组空间大小),使用数组实现
    • LinkedList(),链表实现
    • Vector(数组空间大小),数组实现
    • Stack(),栈实现
  • 特有的方法:get(int 下标)、remove(int 下标)、for + 下标

  • 基本用法和特点:

     向List集合里面添加元素:list.add(Object 元素) -> 因为元素不唯一,所以不作比较,直接加从List集合删除元素:list.remove(int 下标) -> 直接删list.remove(Object 元素)-> 将传入的元素作为参照物,调用本类定义的equals()挨个元素传入比较,为true删除(若本类未定义,使用Object类的equals()比较地址进行删除)判断List集合里是否出现指定的元素:list.contains(Object 元素) -> 将传入的元素作为参照物,调用本类定义的equals()挨个元素传入比较,为true表示存在,方法返回true(若本类未定义,使用Object类的equals()比较地址)当一个对象已添加进集合后,修改某个对象(自定义引用数据类型)的属性,直接修改。如下面的例子:
    
import java.util.*;
public class Example{public static void main(String args[]){Student s1 = new Student("xx", "123");ArrayList<Student> sList = new ArrayList<>();sList.add(s1);sList.add(s1);sList.add(s1);System.out.println(sList);//--->[xx:123, xx:123, xx:123]s1.name = "xx2";System.out.println(sList);//--->[xx2:123, xx2:123, xx2:123]}
}class Student{String name;String tel;public Student(String name, String tel){this.name = name;this.tel = tel;}@Overridepublic String toString(){return name + ":" + tel;}
}
  • ArrayList和LinkedList之间的区别?

    • ArrayList和LinkedList底层采用的数据结构不同 导致优劣势不同

    • ArrayList:底层基于数组实现,
      优点:随机访问,遍历查找的效率高(可以指定下标对数组进行查找或依据下标遍历查找)
      缺点:增删元素效率低(1.创建新数组对象 2.复制老数组元素 3.改变引用指向 4.回收老数组 )

    • LinkedList:底层基于双向循环链表实现,
      优点:增删元素效率高(直接通过改变地址指向进行增删)
      缺点:不能随机访问,遍历查找效率低(每次遍历查找都需要从头找起)

在开发的时候,尽量避免使用LinkedList的get(int 下标)方法
ArrayList更适合访问、读取数据,LinkedList适合增删数据

  • ArrayList和Vector之间的区别?

    • 同步线程不同
      Vector同一时间允许单个线程进行访问,效率较低,但不会出现并发错误;
      ArrayList同一时间允许多个线程访问,效率较高,但可能出现并发错误。

    • 扩容机制不同
      ArrayList和Vector的初始长度都是10,但扩容机制不同,
      Vector分构造方法,(Vector(10) -> 2倍扩容 10->20->40->80…;Vector(10,3)->定长扩容 10->13 ->16->19…);
      ArrayList分版本(JDK6.0之前 x * 3 / 2 + 1;JDK7.0之后 x + (x >> 1))。

    • 出现的版本不同
      Vector出现于JDK1.0;
      ArrayList出现于JDK1.2。

JDK5.0开始,集合的工具类(Collections)里面提供的一个方法(synchronizedList)可以将线程不安全的ArrayList对象变成线程安全的集合对象,于是Vector渐渐被淘汰。

6.3 Set(无序,唯一)

  • 父接口:Collection

  • 子接口:SortedSet

  • 实现类:HashSet(分组组数,加载因子),基于哈希表实现,默认参数为16、0.75。

  • 特有的方法:无

  • 基本用法及特点:

      向Set集合中添加元素:set.add(Object 元素) -> 需逐步验证hashCode()、 ==、 equals()来确定唯一性从Set集合中删除元素时:set.remove(Object 元素) -> 需以这个元素根据hashCode()、==、equals()逐个判断是否有这样的元素判断Set集合里是否出现指定元素:set.contains(Object 元素) -> 需以这个元素根据hashCode()、==、equals()逐个判断是否有这样的元素当一个对象已经添加进HashSet集合之后,不要随意的修改。如果一定要修改那些用于生成哈希码的属性值,需先删除、再修改和添加。
    
  • ArrayList、LinkedList、HashSet集合分别使用什么应用场景?

    • ArrayList:按照添加顺序排序,对元素没有唯一要求,查找元素频时
    • LinkedList:对元素没有唯一要求,添加/删除元素频繁时
    • HashSet:当对元素有唯一要求,但是对排序无要求时

6.4 SortedSet(有序,唯一)

  • 父接口:Set

  • 实现类:TreeSet(比较器对象),比较器对象可选,基于二叉树实现。

  • 特有的方法:first()、last()、pollFirst()、pollLast()

  • 特点:

      向TreeSet集合中添加元素时,需在比较器或实现的比较方法中验证唯一性并确定添加后的位置:set.add(元素) ->implements Comparable -> compareTo(XXX)->implements Comparator -> compare(XXX,YYY)从TreeSet集合里删除元素时,需根据比较器或实现的比较方法中验证唯一性并确定添加后的位置:set.remove(Object 元素) -> implements Comparable -> compareTo(XXX)-> implements Comparator -> compare(XXX,YYY)判断TreeSet集合里面是否出现指定元素,同样:set.contains(Object 元素) -> implements Comparable -> compareTo(XXX)-> implements Comparator -> compare(XXX,YYY)*:当一个对象已经添加进TreeSet集合后,不要随意的修改那些参与排序的属性值,如果一定要修改,先删除这个元素对象,然后修改对象,再添加回去。
    

6.5 所有单值集合都有的方法

add(obj)、remove(obj)、size()、iterator()、contains(obj)、clear()、addAll()(取两个集合的并集,如果是唯一性的单值集合,将合并重复的元素)、removeAll()、retainAll()(取两个集合交集)

【第17天】Java集合(四)---Sorted接口实现的TreeSet集合及单值类型集合总结相关推荐

  1. java hashedmap_Java基础 - Map接口的实现类 : HashedMap / LinkedHashMap /TreeMap 的构造/修改/遍历/ 集合视图方法/双向迭代输出...

    import java.util.*; /**一:Collection接口的 * Map接口: HashMap(主要实现类) : HashedMap / LinkedHashMap /TreeMap ...

  2. java集合框架的接口_Java集合框架——Set接口

    第三阶段 JAVA常见对象的学习 集合框架--Set接口 List集合的特点是有序的,可重复的,是不是存在这一种无序,且能保证元素唯一的集合呢?(HashSet )这就涉及到我们今天所要讲的Set集合 ...

  3. Java集合框架——List接口

    第三阶段 JAVA常见对象的学习 集合框架--List接口 image 按照集合框架的继承体系,我们先从Collection中的List接口开始学习 (一) 概述及功能(ArrayList演示) (1 ...

  4. 49天精通Java,第23天,Java集合,Collection接口,Iterator接口

    目录 一.Collection接口 二.Iterator接口 1.Iterator接口方法 2.遍历 3.forEach 4.遍历元素的顺序取决于集合类型 三.Java集合 四.分布式中间件核心原理与 ...

  5. Educoder第1关:学习-Java集合类之Collection接口之往集合中添加元素

    ##educoer 第1关:学习-Java集合类之Collection接口之往集合中添加元素 任务:接收给定的一行字符串,实现如下需求: 1.通过空格(一个)切割字符串: 2.创建任意一种类型的集合: ...

  6. 【Java基础】-【集合:Map接口 】

    一.Map接口 1.Map接口概述 将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值. 2.Map接口和Collection接口的不同 ①Map是双列的,Collection是 ...

  7. java 集合 接口_Java集合之Collection接口

    1 - Java集合介绍 /* 1. 一方面, 面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象 的操作,就要对对象进行存储. 2. 另一方面,使用Array存储对象方面具有一些弊 端,而 ...

  8. java实验四 集合与函数式编程实验

    (2020.4.28版) desktop/javacode/javatesthomework4 5.12版 改了StudentServiceImpl 为stream方式 5.19 优化removeif ...

  9. java 集合(Set接口)

    Set接口:无序集合,不允许有重复值,允许有null值 存入与取出的顺序有可能不一致 HashSet:具有set集合的基本特性,不允许重复值,允许null值 底层实现是哈希表结构 初始容量为16 保存 ...

最新文章

  1. java红黑树_JAVA学习-红黑树详解
  2. spring-aop-01
  3. Qt Creator缩进文字或代码
  4. 周思进:自知“能力不足“让我专注十几年音视频
  5. java调用julia脚本,Julia请求脚本中的用户输入
  6. 常用SEO优化之META标签
  7. js 循环拆词_javascript forEach通用循环遍历方法
  8. 【2016年第1期】从政策驱动到技术践行:大数据开辟可持续发展研究新途径
  9. YOLOv3目标检测有了TensorFlow实现,可用自己的数据来训练
  10. 2021-2025年中国道路平地机行业市场供需与战略研究报告
  11. 全球顶级开源大神们现身 COSCon‘20
  12. PyCharm导入selenium的webdirver模块出错
  13. springboot集成quartz,简版-通俗易懂
  14. 2021 小白版,360 行行行转 IT
  15. win7系统关闭445端口
  16. Sketch 使用快捷键记录
  17. Java||求集合数组中的中位数
  18. luogu P2381 圆圆舞蹈
  19. 教您在MathType输入三角形符号
  20. 中国最美的100首古代情诗

热门文章

  1. codeforces1627C Not Assigning(思维)
  2. autoquad源码分析1
  3. iOS开发者 如何突破自身技术瓶颈,成为别人眼中的 架构师?
  4. 目前得前端框架都有哪些?
  5. 苹果付费app共享公众号_【苹果iOS付费游戏应用帐号分享】新增一款25元iOS游戏应用共享帐号...
  6. python微信好友分析源代码_Python简单分析微信好友
  7. 彻底搞懂MySql的B+Tree
  8. Win7/R2 原生VHD 启动 详解
  9. select into from 和 insert into select的使用
  10. 自然语言处理 第二期