1. Collections用法

Collections: 集合的工具类
public static <T> void sort(List<T> list) 排序,升序
public static <T> int binarySearch(List<?> list,T key) 二分查找,不存在返回负数,只能针对升序集合
public static <T> T max(Collection<?> coll) 最大值
public static void reverse(List<?> list) 反转

public static void shuffle(List<?> list) 随机打乱
public static <T> void sort(List<T> list, Comparator<? super T> c)

Collection 和Collections 区别:
  Collection: 是单列集合的根接口
  Collections: 集合的工具类

2. 比较器***

2.0 前提

通过Collections.sort()方法已经可以对一些集合实现排序功能,如下对List<Integer> list进行了排序

public class ComparableDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(100);
list.add(124);
list.add(99);
list.add(300);
Collections.sort(list);
System.out.println(list);//[99, 100, 124, 300]
}
}

此时若将集合改为List<Person>会直接报错,如下(The method sort(List<T>) in the type Collections is not applicable for the arguments (List<Person>))

排序是通过Collections.sort()方法,那么,为什么List<Integer>可以进行排序呢?我们可以去看下Collections下sort方法以及Integer源码

sort()源码部分

由此处可看出,sort内的参数类型必须是Comparable<? super T>本身或者其父类,接下来看下Integer的源码部分

可见其继承类Comparable<Integer>接口,那么如何让List<Person>类型的list也为comparable类型呢,首先想到的是继承,让Person类继承Integer类,Person就自然符合sort()方法中的参数类型了,但是有上面Integer源码可知,Integer有final修饰,其是不能被继承的,没办法,只能自己去继承并实现Comparable接口了。查看Comparable接口的源码,发现发现接口内部有个抽象方法待实现(compareTo()),而这个方法便是定义排序规则的,以便sort可以按此规则对list进行排序。这里我们先看下Integer类中是怎么实现comparable接口的,查看起源码,如下:

可见实现compareTo的方法最终返回值有三种(0,-1,1),但sort()是怎么实现这个排序的呢?(以后再去看详细的源码)

大致调用过程如下:

Collections.sort()----->list.sort()------->Arrays.sort()------>Arrays.legacyMergeSort()----->Arrays.mergeSort()   ,可见,最终是用归并排序来实现的

所以,要利用Collections.sort()对List<Person>集合进行排序,只需让Person实现Comparable接口即可(可参照Integer类)

2.1 Comparable用法

(1)

  要想让一个List可以使用Collections.sort进行排序,需要要求集合中的元素所在的类实现Comparable(java.lang)接口,实现了该接口就具备了排序的能力,才能进行排序,实现该接口我们需要重写里面的compareTo方法,该方法的主要目的就是定义排序的规则(即告诉接口按照上面规则比较大小),重写该方法时要注意,该方法返回值是int类型

  返回值为正数,表明this中的数据大于参数中的数据,排序时将大的数移至后面

  返回值为0,表明this中的数据等于参数中的数据

  返回值为负数,表明this中的数据小于参数中的id

其实就是this对象和参数对象做一个比较,this对象在前,就是升序,参数对象在前就是降序。

以下将Person去实现Comparable接口(只写出重写方法部分代码):

@Override
public int compareTo(Person o) {
return (this.age<o.age)?-1:(this.age==o.age)?0:1;
}

这样的话Collections.sort()就可以对List<Person>集合进行排序,具体如下(此处是按年龄排序)

public class ComparableDemo {
public static void main(String[] args) {
List<Person> person = new ArrayList<Person>();
person.add(new Person("zs",26,'男'));
person.add(new Person("ls",36,'男'));
person.add(new Person("xh",26,'女'));
person.add(new Person("mz",16,'女'));
Collections.sort(person);
System.out.println(person);
}
}
// 运行结果:[Person [name=mz, age=16, gender=女], Person [name=zs, age=26, gender=男], Person [name=xh, age=26, gender=女], Person [name=ls, age=36, gender=男]]

若要按姓名来排序,并且降序则compareTo方法如下:

public int compareTo(Person o) {
return o.name.compareTo(this.name);// 此处的compareTo为字符串内实现的compareTo方法
}

同样是上面的 ComparableDemo测试类,得到的结果为

[Person [name=zs, age=26, gender=男], Person [name=xh, age=26, gender=女], Person [name=mz, age=16, gender=女], Person [name=ls, age=36, gender=男]]

练习:创建一个Student类型的List:姓名,年龄,分数,排序要求:按照年龄做升序,如果年龄相同,则按照分数做降序

public class Student implements Comparable<Student>{
  String name;
  int age;
  double score;
  public Student() {

  }
  public Student(String name, int age, double score) {
    super();
    this.name = name;
    this.age = age;
    this.score = score;
  }
  @Override
  public String toString() {
    return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
  }
  //需求: 默认按照年龄的升序,如果年龄相同,按照分数的降序
  @Override
  public int compareTo(Student o) {
    if(this.age == o.age) {
  //return (int)(o.score - this.score);//这么写不好,98.6 98.7得到的结果是0
    //  会认为分数相同,就会按照添加的顺序排序,和预期不符
   return o.score - this.score>0?1:-1; } return this.age - o.age; } }

2.2  comparator用法

  1.  好了,目前我们已经掌握了如何对一个List<Person>做排序,那么我们知道了为什么List<Integer>默认实现的是升序,就是因为Integer在实现Comparable接口的时候用的就是升序的方式,如果我们想要实现降序应该怎么做呢?其实只需要将Integer中的compareTo方法中的两个参数调换一下位置就可以了,但是由于是class文件,我们是不能修改的,所以java为我们提供了一个外部比较器Comparator(java.util),这是个接口

public class ComparableDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(100);
list.add(124);
list.add(99);
list.add(300);
Collections.sort(list,new IntegerComparator());//注意此处的sort方法跟升序不是一个方法,这是提供给 comparator的重载方法,接收2个参数
System.out.println(list);//[99, 100, 124, 300]
}
}
class IntegerComparator implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
}
// 运行结果:[300, 124, 100, 99]

2. 为了简便,可进行如下改写:

  (1)使用匿名函数来实现comparator接口

Collections.sort(list, new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});

(2)在java1.8后,可以直接调用list.sort(),不需要Collections(更加方便),如下

list.sort(new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});

(3)使用lambda方法

list.sort((a,b)->b-a);

 3. 此处可以不用Collections.sort(),直接使用带参数的构造方法,具体如下

2  总结

 Comparator:用法:

    Collections.sort(List<List>, Comparator<>); 

 由于Comparator是一个接口,需要传入Comparator子类的对象(匿名内部类),需要重写compare,从而定义新的排序规则

    用前面的和后面的比较:升序

    用后面的和前面的比较:降序

 Comparable  和 Comparator的区别:

    Comparable:内部比较器,位于java.lang,如果一个集合想要使用Collections.sort进行排序,需要里面的元素所在类实现Comparable接口,并且重写compareTo方法实现排序

3.  TreeSet和TreeMap的用法

3.1TreeSet

  Collections.sort()只能作用于list,并不能作用于Set。Set要排序的话可以通过其子类TreeSet,TreeSet会自动对集合中的元素进行排序,同List一样,其对Person这种类型的元素做排序时,需要在这种类中实现Comparable接口,否则会出现转型异常:com._51doit.javase04.day15.tree.Person cannot be cast to java.lang.Comparable。

案例1

public class TreeSetDemo {
public static void main(String[] args) {
Set<Integer> set = new TreeSet<Integer>();
set.add(12);
set.add(15);
set.add(20);
set.add(9);
System.out.println(set);
}
}
// 运行结果:[9, 12, 15, 20]

由结果可知,TreeSet可实现自动排序

Set实现comparable接口的方式就是直接重载compareTo方法就行了,其内部是自动调用了排序方法的,但comparator则有点不一样,重写完comparator中的compare方法,直接将这个子类对象传进集合构造方法,具体如下:

public class TreeSetDemo1 {
public static void main(String[] args) {
//实现TreeSet中Integer降序
Set<Integer> set3 = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
set3.add(123);
set3.add(45);
set3.add(1);
set3.add(100);
System.out.println(set3);
}
}
// 运行结果:[123, 100, 45, 1]

注意  Set里面的元素不能重复,其判断元素是否重复的原理是:根据compareTo(对comparable)/compare(对comparator)方法来验证元素是否重复,compareTo/compare返回结果是0,就认为是相同的元素,否则就不同。我们在重写compareTo/compare方法的时候,尽量不要只比较一个属性

案例2

public class TreeSetDemo {
public static void main(String[] args) { Set<Teacher> teacher = new TreeSet<Teacher>();
teacher.add(new Teacher("zs",26));
teacher.add(new Teacher("ls",36));
teacher.add(new Teacher("xh",26));
teacher.add(new Teacher("xf",26));
teacher.add(new Teacher("mz",16));
System.out.println(teacher); //并没有调用排序方法,重写compareTo方法直接打印此set集合,就会按照compareTo定义的规则排序,其内部怎么实现排序的暂不清楚
}
}
class Teacher implements Comparable<Teacher>{
String name;
int age;
public Teacher(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int compareTo(Teacher o) {
return o.age - this.age; //按年龄降序
}
@Override
public String toString() {
return "Teacher [name=" + name + ", age=" + age + "]";
}
}
// 运行结果:[Teacher [name=ls, age=36], Teacher [name=zs, age=26], Teacher [name=mz, age=16]]

有结果可知,TreeSet直接按年龄是否相同去重了,若要不被去重,可以在compareTo中多写几个属性,如下

@Override
public int compareTo(Teacher o) {
if(o.age == this.age) {
return o.name.compareTo(this.name);//降序
}
else {
return o.age - this.age;// 降序
}
}
// 运行结果: [Teacher [name=ls, age=36], Teacher [name=zs, age=26], Teacher [name=xh, age=26], Teacher [name=xf, age=26], Teacher [name=mz, age=16]]

3.2 TreeMap

1. 概述:

TreeMap:可以对key这一列实现排序,key不能为nul(key会调用compare/compareTo方法进行排序,若为null,则会出现空指针异常),TreeMap中的key所在的类必须要实现Comparable接口,如果不想实现,则必须在构造方法中传入一个外部比较器。

key:   不能重复,其原理也是由compare/compareTo方法决定的

public class TreeMapDemo {
public static void main(String[] args) {
TreeMap<Integer,String> map = new TreeMap<>();
map.put(1,"热河");
map.put(2,"你好");
map.put(3,"再见");
//map.put(null,"热河"); 报空指针异常
System.out.println(map);
}
}
运行结果:{1=热河, 2=你好, 3=再见}

2.TreeMap实现降序

  使用外部选择器:Comparator(此处能不能通过重写comparable中的compareTo方法来实现降序呢?)

public class TreeMapDemo {
public static void main(String[] args) {
TreeMap<Integer,String> map = new TreeMap<>(new Comparator<>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
map.put(1,"热河");
map.put(2,"你好");
map.put(3,"再见");
System.out.println(map);
}
}

运行结果:{3=再见, 2=你好, 1=热河}

  

4. 异常

4.0 概述:  

  异常就是java程序在运行过程中出现的错误,现实生活中遇到的问题也是一个具体的事务,可以通过java类的形式进行描述,并封装成对象。其实就是java对不正常情况进行描述后的对象体现。前面见过的异常有角标越界异常,空指针异常等。

4.1 异常的层次结构:

Throwable:

  Error:程序出现的错误,不能使用程序处理,一般无需程序员关注,如内存溢出,网络连接异常

  Exception(异常):

        运行时异常:RuntimeException及其子类,可以对其进行处理,也可以不处理,往往是由于代码书写不正确或不规范造成,程序员自己去检查问题,并修改代码。

        编译时异常:除了运行时异常以外的所有异常,必须对异常进行处理,否则无法通过编译,程序无法执行往往是由于无法预估的用户操作造成的

产生异常后:代码无法向下执行

我们处理异常的目的是什么?   为了让程序能够执行下去

下面是编译时异常

4.2 异常的处理方式:

JVN处理异常的方式:

    打印异常信息并终止程序,其并不会对异常进行处理

当出现异常时,在eclipse找异常的顺序是由上往下,上面的异常一般为异常产生处,如下(先是test出现异常,再是main,而main方法出现异常是因为调用了test方法)

4.2.1  捕获:

  1.try...catch( ){  }

    格式:

       try{

         //可能出现的异常

          }catch(异常类名   对象名){

           //对异常的处理

       }

  2.try...catch...finally

    格式:   

      try{

         //可能出现的异常

          }catch(异常类名   对象名){

           //对异常的处理

       }finally{

           //一定会执行的代码

       }

注意事项:

1. catch 块中可以存在多个,并且可以有子父类的关系:
   一旦存在子父类的关系,要把子类异常放上面,因为放下面,就再也执行不到了
      catch 块中应该写的是一种备选方案
2. jdk7:一个catch 块中可以处理多个异常,多个异常之间使用 | 隔开
3. try 块中的局部变量和catch 块中的局部变量(包括异常变量),以及finally 中的局部变量,他们之间不可共享使用。
4. 每一个catch 块用于处理一个异常。异常匹配是按照catch 块的顺序从上往下寻找的,只有第一个匹配的catch 会得到执行。匹配时,不仅运行精确匹配,也支持父类匹配,因此,如果同一个try 块下的多个catch 异常类型有父子关系,应该将子类异常放在前面,父类异常放在后面,这样保证每个catch 块都有存在的意义。
5. 当一个函数的某条语句发生异常时,这条语句的后面的语句不会再执行,它失去了焦点。执行流跳转到最近的匹配的异常处理catch 代码块去执行,异常被处理完后,执行流会接着在“处理了这个异常的catch 代码块”后面接着执行。
6. finally 块不管异常是否发生,只要对应的try 执行了,则它一定也执行。只有一种方法让finally 块不执行:System.exit()。因此finally 块通常用来做资源释放操作:关闭文件,关闭数据库连接等等

public class ExceptionDemo {
public static void main(String[] args) {
Date d = null;
try {
System.out.println(1/0); // 运行时异常
}catch(Exception e1){
System.out.println("哈哈");
}
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
d = sdf.parse("1232012-09-18"); // 编译时异常
String s = null;
System.out.println(s.length()); // 空指针异常
System.out.println(1/0);
}catch(ArithmeticException | NullPointerException e) { // 1个catch块处理多个异常
System.out.println("1");
}catch(Exception e) { //此异常不能放前面,不然前面catch就不能执行了
d = new Date();
}
}
}

面试题:

  final           finalize            finally:区别:  

final:     修饰类、方法、变量,被修饰的类不能被继承,被修饰的方法不能重写,被修饰的变量值不变
finalize: 用于垃圾回收

finally:   用于异常处理,代表一定会执行的代码

4.2.2  抛出(throws)

格式:

 在方法头上:throws  异常类名{  // 类名可以有多个,多个类之间使用“,”隔开

  } 

注意:异常最终被抛给了异常的调用者

public class ExceptionDemo1 {
public static void main(String[] args) throws ParseException {// 抛给其调用者JVM
test();
}
public static void test() throws ParseException { // 抛给其调用者main方法
new SimpleDateFormat().parse("");
}
}

一般内层抛出,在最外层做统一处理(不然每调用一次出现异常的方法就要处理一次异常)

 4.3  异常中常用的方法

 4.3.1  Trowable中的方法

(1)getMessage(): 获取异常信息,返回字符串。

public class ExceptionDemo2 {
public static void main(String[] args) {
try {
new SimpleDateFormat().parse("");
}catch(ParseException e){
System.out.println(e.getMessage());
}
}
}
// 运行结果:Unparseable date: ""

(2)toString():获取异常类名和异常信息,返回字符串

System.out.println(e.toString());  // java.text.ParseException: Unparseable date: ""

(3)printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void(不需要System.out.print(),自身就有打印功能)

e.printStackTrace(); // 打印异常信息,打印到控制台

运行结果:如下图

4)printStackTrace(PrintStream s):通常用该方法将异常内容保存在日志文件中,以便查阅

public class ExceptionDemo2 {
public static void main(String[] args) {
try {
new SimpleDateFormat().parse("");
}catch(ParseException e){
e.printStackTrace();
try {
e.printStackTrace(new PrintStream("f:/a/error.txt"));
}catch(FileNotFoundException e1) {
e1.printStackTrace();
}
}
}
}

4.4 throw用法

throw 不是用来处理异常的,相反是触发一个异常,或者理解成一个异常

格式:

  用在方法体中,throw异常的对象,这个对象只能有一个

throw的异常一定会发生

public class ExceptionDemo3 {
public static void main(String[] args) {
test();
}
public static void test() {
throw new NullPointerException(""); // 若加参数,在报错异常类后会出现该参数
}
}

运行结果:

若创建的是编译异常,则要抛出或者处理异常

public class ExceptionDemo3 {
public static void main(String[] args) {
try {
test();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void test() throws ParseException {
throw new ParseException("天空之城",30); //此处的inr参数表示当编译时,错误会在那个位置发生(不大理解)
}
}

 4.5 throws和throw区别

throws:

  用在方法声明后面,跟的是异常类名;可以跟多个异常类名,用逗号隔开,表示抛出异常,由该方法的调用者来处理;throws表示出现异常的一种可能性,并不一定会发生这些异常

throw:

  用在方法体内,跟的是异常对象名;只能抛出一个异常对象名;表示抛出异常,由方法体内的语句处理;throw则是抛出了异常,执行throw则一定抛出了某种异常

 4.6 自定义异常

  定义编译时异常:继承Exception

  定义运行时异常:继承RunException

案例:人的年龄必须在1-260,显然java没有对应的异常,需要我们自己来定义一个异常,如下:

(1)定义运行时异常: 

定义一个继承自RuntimeException的异常,即运行时异常

public class MyException extends RuntimeException {
public MyException() {};
public MyException(String desc) {
super(desc);
}
}

定义测试类,以及抛出异常

public class AgeTest {
public static void main(String[] args) {
AgeException ae = new AgeException();
ae.setAge(300);
}
}
class AgeException {
int age; public int getAge() {
return age;
}
public void setAge(int age) {
if(age>=1 && age<=260) {
this.age = age;
}else {
throw new MyException("您的年龄有问题");
}
}
}

运行结果

(2)定义编译时异常:

将MyException继承自Exception即可,改完后,测试类中的年龄部分就要抛出异常或者处理异常了

 4.7  异常的注意事项

(1)子类重写父类方法时,子类的方法必须要抛出相同的异常或父类异常的子类

class FatherClass{
public void test() throws Exception{ }
}
class SonClass extends FatherClass{
public void test() throws ParseException{ }
}
若将ParseException与Exception调换则会报错:Exception Exception is not compatible with throws clause in FatherClass.test()

(2)如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是它的子集,子类不能抛出父类没有的异常

(3)如果被重写的方法没有异常抛出,那么子类方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws

(4)以上异常指的都是编译时异常 

零基础学习java------day15--------collections用法,比较器,Set(TreeSet,TreeMap),异常的更多相关文章

  1. 音乐出身的妹纸,零基础学习JAVA靠谱么

    问:表示音乐出身的妹纸一枚  某一天突然觉得身边认识的是一群程序员   突然想 要不要也去试试... 众好友都觉得我该去做个老师,可是我怕我会误人子弟,祸害祖国下一代..... 要不要 要不要 学Ja ...

  2. 总结了零基础学习Java编程语言的几个基础知识要点

    很多Java编程初学者在刚接触Java语言程序的时候,不知道该学习掌握哪些必要的基础知识.本文总结了零基础学习Java编程语言的几个基础知识要点. 1先了解什么是Java的四个方面   初学者先弄清这 ...

  3. 【转】【Salesforce】salesforce 零基础学习(十七)Trigger用法

    看本篇之前可以相应阅读以下Trigger相关文章: 1.https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigge ...

  4. salesforce 零基础学习(五十二)Trigger使用篇(二)

    第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. ...

  5. 【零基础学习iOS开发】【转载】

    原文地址:http://www.cnblogs.com/mjios/archive/2013/04/24/3039357.html 本文目录 一.什么是iOS 二.主流手机操作系统 三.什么是iOS开 ...

  6. 李洪强iOS开发之【零基础学习iOS开发】【01-前言】01-开篇

    从今天开始,我就开始更新[零基础学习iOS开发]这个专题.不管你是否涉足过IT领域,也不管你是理科生还是文科生,只要你对iOS开发感兴趣,都可以来阅读此专题.我尽量以通俗易懂的语言,让每个人都能够看懂 ...

  7. 零基础学习hadoop到上手工作线路指导

    零基础学习hadoop,没有想象的那么困难,也没有想象的那么容易.在刚接触云计算,曾经想过培训,但是培训机构的选择就让我很纠结.所以索性就自己学习了.整个过程整理一下,给大家参考,欢迎讨论,共同学习. ...

  8. 【零基础学习iOS开发】【01-前言】01-开篇

    本文目录 一.什么是iOS 二.主流手机操作系统 三.什么是iOS开发 四.学习iOS开发的目的 五.学习iOS开发的前提 从今天开始,我就开始更新[零基础学习iOS开发]这个专题.不管你是否涉足过I ...

  9. salesforce 零基础学习(六十八)http callout test class写法

    此篇可以参考: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restfu ...

  10. 零基础学习Hadoop

    零基础学习hadoop,没有想象的那么困难,也没有想象的那么容易.在刚接触云计算,曾经想过培训,但是培训机构的选择就让我很纠结.所以索性就自己学习了.整个过程整理一下,给大家参考,欢迎讨论,共同学习. ...

随机推荐

  1. PWN二进制漏洞学习指南

    目录 PWN二进制漏洞学习指南 前言 前置技能 PWN概念 概述 发音 术语 PWN环境搭建 PWN知识学习途径 常见漏洞 安全机制 PWN技巧 PWN相关资源博客 Pwn菜鸡小分队 PWN二进制漏洞 ...

  2. SpringBoot2.x异步任务EnableAsync

    1.springboot启动类里面使用@EnableAsync注解开启异步功能 @EnableAsync public class Demo001Application { public static ...

  3. vs Code配置C++运行和调试环境以及相关问题

    vs Code配置C++运行和调试环境以及相关问题 第一步:下载c++插件 第二步:安装编译.调试环境 如果没有Dev-C++下载MinGW 下载地址:https://sourceforge.net/ ...

  4. KMP算法,看这篇就够了!

    普通的模式匹配算法(BF算法) 子串的定位操作通常称为模式匹配算法 假设有一个需求,需要我们从串"a b a b c a b c a c b a b"中,寻找内容为"a ...

  5. OpenXml SDK学习笔记(4):设置文件级别的样式

    观察上一段日记最后的代码: 这里的样式基本可以理解为行内CSS.那么既然有行内的样式,就肯定有外部的样式.那这部分就对应笔记1里说的style.xml文件.这个文件对应的是Document.MainD ...

  6. Linux NameSpace (目录)

    1. User Namespace 详解 2. Pid Namespace 详解 3. Mnt Namespace 详解 4. UTS Namespace 详解 5. IPC Namespace 详解 ...

  7. Django 小实例S1 简易学生选课管理系统 9 创建课程模型(model)

    Django 小实例S1 简易学生选课管理系统 第9节--创建课程模型(model) 点击查看教程总目录 作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师. 对于课程模块, ...

  8. [bzoj2400]Optimal Marks

    首先肯定每一位单独考虑,对于每一位,源点连向该位点权为0的节点inf的边,点权为1的节点连向汇点inf的边,每一条无向边拆成两条流量为1的有向边,跑最小割. 考虑一组割,一定将原图划分成源点和汇点两部 ...

  9. watch异步操作

    异步操作: 1.ajax, 2.定时器 3.点击事件 4.数据库操作 特点:代码不等待,后续代码会继续执行. watch:{ //watch作用监测已经存在的数据 newVal 新值,oldVal 旧 ...

  10. springboot和springcloud版本上的选择

    现在的springboot项目和cloud版本都是更新很快,但我们开发不是版本越新越好,我们要把版本对应起来,那么我们怎么去关联呢? springboot和springcloud不是越新越好,clou ...