JAVA基础2

10.24

内存管理

​ 由JVM来管理

1.内存管理:

  • 堆:

    • 存储new出来的对象(包括实例变量,数组的元素)

    • 垃圾:没有任何引用所指向的对象(垃圾回收期GC会不定时到内存中清扫垃圾),回收过程透明的,不一定一发现垃圾就立刻回收,通过调用System.GC可以建议虚拟机尽快调度GC来回收

    • 实例变量的生命周期

      • 创建对象时存储在堆中,对象被回收时一并回收
    • 内存泄漏:

      • 不再使用的内存还没有被及时的回收就叫泄漏
      • 建议:不再使用的对象应及时将引用设置为null
  • 栈:

    • 存储正在调用的方法中的局部变量(包括方法的参数)
    • 调用方法时,会在栈中为该方法分配一块对应的栈帧,栈帧中存储局部变量(包括方法中的参数),方法调用结束时,栈帧会自动清理,局部变量一并被清除。
    • 局部变量的生命周期:
      • 调用方法时存储在栈中,方法调用结束时与栈帧一并被清除
  • 方法区:

    • 存储.class字节码文件(包括静态变量,所有方法),只存储一份
    • 方法只有一份,用this来区分具体的调用对象

面向对象三大特征

  • 封装:

    • 类:封装的是对象的属性和行为
    • 方法:封装的是具体的业务逻辑功能实现
    • 访问控制修饰符:封装的是具体的访问权限同时也保护了数据安全
  • 继承(体现在重写重载上):

    • 作用:代码复用

    • 超类:所有派生类说共有的属性和行为

      接口:部分派生类所共有的属性和行为

      派生类/实现类/子类:派生类所特有的属性和行为

    • 单一继承,多接口实现,具有传递性

  • 多态:多种形态

    • 所有对象都是多态的——通过向上造型来体现

      所有抽象方法都是多态的——通过方法的重写来体现

    • 向上造型、强制类型转换(向下转换)

  • String字符串类型:

    • java.lang.String类使用final修饰,不能被继承
    • String的底层封装是一个字符数组
    • String在内存中采用的是Unicode编码格式,每个字符占用两个字节的空间
    • 字符串对象一旦创建,对象内容无法改变,但是字符串引用可以重新赋值
      • 将String称为不变对象
  • 字符串常量池:

    • java对String字符串有一个优化方式:字符串常量池

    • java推荐我们使用字面量/直接量(直接“”)的方式创建字符串对象,并且会缓存所有以字面量方式创建的字符串对象到常量池中,

      当使用相同字面量再创建字符串对象时将会复用常量池中的对象,以减少内存的开销

      /**
      	使用字面量来创建字符串对象时,JVM会检查常量池中是否有该对象
      	若没有,则会创建字符串对象,并将其引用存入到常量池中
      	若有,则直接将常量池中的对象(引用)返回,并不会创建新的字符串对象
      */
      String s1 = "123abc";
      String s2 = "123abc";
      String s3 = "123abc";
      /**引用类型==,比较的是地址是否相同--这是规定*/
      sout(s1==s2);
      sout(s2==s3);
          
      s1 = s1+"!";	//用拼接方式创建新的字符串对象 并将地址赋给s1
      System.out.println(s1 == s2);//false
      
      String s1 = "123abc";//堆中创建“123abc”字面量对象,并缓存到常量池中
      String s2 = "123"+"abc";//编译器在编译时,若发现时两个字面量相连,则会直接连接好并将对象保存起来
      System.out.println(s1 == s2)//复用常量池中的对象
      String s3 = "123"
      String s4 = s3 + "abc";//s3是一个变量,所以在编译期不会直接编译好,所以创建一个新的对象存储123abc
      System.out.println(s1 == s4);
      

10.24补充

public class Test {
    public static void main(String[] args) {
        Aoo o1=new Aoo();
        Boo o2 = new Boo();
        Aoo o3 = new Boo();
    }
}
class Aoo{
    static {
        System.out.println("我是静态块");
    }
    {
        System.out.println("我是语句块");
    }
    Aoo(){
        System.out.println("我是构造方法");
    }
}

class Boo extends Aoo{
    static {
        System.out.println("我是Boo静态块");
    }
    {
        System.out.println("我是Boo语句块");
    }
    Boo(){
        System.out.println("我是Boo静态方法");
    }
}

输出结果:

  1. 只输出Aoo o1 = new Aoo()

    我是静态块
    我是语句块
    我是构造方法

  2. 只输出Boo o2 = new Boo();

    我是静态块
    我是Boo静态块
    我是语句块
    我是构造方法
    我是Boo语句块
    我是Boo静态方法

  3. 只输出Aoo o3 = new Boo();

    我是静态块
    我是Boo静态块
    我是语句块
    我是构造方法
    我是Boo语句块
    我是Boo静态方法

总结:超类静态块>派生类静态块>超类语句块>超类静态方法>派生类语句块>派生类静态方法

文档注释

  1. 是一种功能性的注释,用于描述某个东西

10.25

String的常用方法

  1. length():获取字符串长度
  2. trim():消除字符串两端的空白字符
  3. boolean startsWith(String s)/boolean endsWith(String s):判断指定的字符串是否为字符串的开头或结尾
  4. toUpperCase/toLowerCase():将当前字符串的英文部分全部转换为大小写,比如验证码不区分大小写
  5. charAt();字符串具体的位置是哪一个字符
  6. IndexOf();/lastIndexOf(); 检索指定字符串在当前字符串中第一次或最后一次出现的位置
  7. substring(); (包头不包尾)截取当前字符串中指定范围的字符串
  8. 静态方法 valueOf() 将其它数据类型转化为String

StringBuilder

  • 由于String是不变对象,每次修改都会创建新的对象,因此String不适合频繁修改操作,为了解决这个问题就提供了StringBuilder类
  • StringBuilder是专门用于修改字符串的一个类,内部维护一个可变的char数组,所做操作都是在这个数组之上进行的,修改速度、性能优秀,并且提供了修改字符串的常见方式:增删插改。

StringBuilder常用方法

  • append():追加内容——增

  • delete():删除部分内容——删

  • replace():替换部分内容——改

  • insrt():插入内容——插

补充

  1. 数组是length类型,String字符串是length方法

  2. 字符串内容若是需要查看,则建议String——————实际应用一般都是查看

    字符串内容若需要频繁修改,则建议StringBuilder

  3. StringBuilder和StringBuffer的区别:——————常见面试题 周五讲

getter/setter

		public class Point {
    /*
      数据私有,设计getter/setter的原因:
      1)很多框架都是基于getter/setter来配置获取数据的,可以理解为它是一种行业的标准
      2)getter/setter时可以对数据进行控制,而public权限时无法对数据进行控制
      3)getter/setter并非一定要同时出现,可以只getter或只setter,需要根据需求自行选择
     */
    private int x;
    private int y;

    public int getX(){ //getter
        return x;
    }
    public void setX(int x){ //setter
        this.x = x;
    }

    public int getY(){
        return y;
    }
    public void setY(int y){
        this.y = y;
    }
}

public class GetterSetterDemo {
    public static void main(String[] args) {
        Point p = new Point();
        p.setX(100);
        p.setY(200);
        System.out.println(p.getX()+","+p.getY());
    }
}

10.25晚间

面试自我介绍


10.26

正则表达式

  1. 用于描述字符串的内容格式,使用它通常用于匹配一个字符串是否符合格式要求
  2. 正则表达式语法:(只用记不用深入)

1.[]:表示一个字符,该字符可以是[]中指定的内容
例如:

2.预定义字符:
.:表示任意一个字符,没有范围限制
\d:表示任意一个数字,等同于[0-9]
\w:表示任意一个单词字符,等同于a-zA-Z0-9_----单词字符指字母、数字和_
\s:表示任意一个空白字符
\D:不是数字
\W:不是单词字符
\S:不是空白字符
3.量词:
?:表示前面的内容出现0-1次
例如: abc? 可以匹配:a 或 b 或 c 或什么也不写
但是不能匹配:m或aaa
+:表示前面的内容最少出现1次
例如: abc+ 可以匹配:b或aaaaaaaaaa…或abcabcbabcbabcba…
但是不能匹配:什么都不写 或 abcfdfsbbaqbb34bbwer…
:表示前面的内容出现任意次(0-多次)—匹配内容与+一致,只是可以一次都不写
例如: abc
可以匹配:b或aaaaaaaaaa…或abcabcba…或什么都不写
但是不能匹配:abcfdfsbbaqbb34bbwer…
{n}:表示前面的内容出现n次
例如: abc{3} 可以匹配:aaa 或 bbb 或 aab 或abc 或bbc
但是不能匹配: aaaa 或 aad
{n,m}:表示前面的内容出现最少n次最多m次
例如: abc{3,5} 可以匹配:aaa 或 abcab 或者 abcc
但是不能匹配:aaaaaa 或 aabbd
{n,}:表示前面的内容出现n次以上(含n次)
例如: abc{3,} 可以匹配:aaa 或 aaaaa… 或 abcbabbcbabcba…
但是不能匹配:aa 或 abbdaw…
4.()用于分组,是将小括号里面的内容看做是一个整体
例如: (abc){3} 表示abc整体出现3次. 可以匹配abcabcabc
但是不能匹配aaa 或abc 或abcabccba
(abc|def){3}表示abc或def整体出现3次.
可以匹配: abcabcabc 或 defdefdef 或 abcdefabc
但是不能匹配abcdef 或abcdfbdef

String支持的正则表达式的相关方法

  1. matches(String regex):使用给定的正则表达式验证当前字符串的格式是否符合要求,若符合则返回true,否则返回false

    public class MatchesDemo {
        public static void main(String[] args) {
            /*
              邮箱正则表达式:
                [a-zA-Z0-9_]+@[a-zA-Z0-9]+(\.[a-zA-Z]+)+
                注意: \.中的\是正则表达式中的转义符
                     \\.中的第1个\,是在转义正则表达式中的\
             */
            String email = "wangkj@tedu.cn";
            String regex = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";
            //使用regex匹配email是否符合格式要求
            boolean match = email.matches(regex);
            if(match){
                System.out.println("是正确的邮箱格式");
            }else{
                System.out.println("不是正确的邮箱格式");
            }
        }
    }
    
  2. replaceAll():将当前字符串中满足正则表达式的部分给替换为给定的字符串

    public class ReplaceAllDemo {
        public static void main(String[] args) {
            String line = "abc123def456ghi78";
            //将数字部分给替换为#NUMBER#
            line = line.replaceAll("[0-9]+","***");
            System.out.println(line);
        }
    }
    
  3. String[] split():将当前字符串按照满足正则表达式的部分进行拆分,将拆分出的以String[]形式来返回

    public class SplitDemo {
        public static void main(String[] args) {
            String line = "abc123def456ghi";
            String[] data = line.split("[0-9]+"); //按数字拆分(数字就拆没了)
            System.out.println(Arrays.toString(data)); //将data数组转换为字符串并输出
    
            line = "123.456.78";
            data = line.split("\\."); //按.拆(.就拆没了)
            System.out.println(Arrays.toString(data));
    
            //最开始就是可拆分项(.),那么数组第1个元素为空字符串-----------""
            //如果连续两个(两个以上)可拆分项,那么中间也会拆出一个空字符串----""
            //如果末尾连续多个可拆分项,那么拆出的空字符串被忽略
            line = ".123.456..78........";
            data = line.split("\\."); //按.拆(.就没有了)
            System.out.println(Arrays.toString(data));
            System.out.println(data.length); //5
        }
    }
    

object(toString,equals)

  1. 所有类的鼻祖,所有类都直接或间接继承了Object,万物皆对象

  2. object中有两个经常被派生类重写的方法

    • toString:调用object的toString时默认会返回类的全称@地址,没有参考意义,所有我们常常重写toString()来返回具体的属性值

      注意:String,StringBuilder已经重写了toString()类型

    • 调用object的equals()内部还是在比较地址,若想比较对象的属性值是否相同,我们认为Object的equals()并不能满足需求,因此常常需要重写equals()

      注意:

      1. String已经重写了toString()类型,但是StringBuilder没有重写
      2. 重写equal()的基本原则:
        • 原则上要比较两个对象的属性值是否相同
        • 两个对象必须是同一类型的,若类型不同则返回false

包装类(使基本类型向引用类型转换)

  • java定义了8个包装类,目的就是为了解决基本类型不能直接参与面向对象的问题,使基本类型可以通过包装类的形式出现

  • 包括:Integer,Character,Byte,Short,Long,Float,Double,Boolean,其中Charater和Boolean是直接继承自Object的,其余六个包装类继承自

    java.lang.Number类

    • 以下代码是Interger中的底层源码IntegerCache,当Integer i2 = 100时 cache数组会从里面返回一个100,当Integer i1 = 100时 cache数组会从里面返回一个100 所以两者i1 == i2 ,100换成200时则错误
    private static class IntegerCache {
            static final int low = -128;
            static final int high;
            static final Integer cache[];
    
            static {
                // high value may be configured by property
                int h = 127;
                String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
                if (integerCacheHighPropValue != null) {
                    try {
                        int i = parseInt(integerCacheHighPropValue);
                        i = Math.max(i, 127);
                        // Maximum array size is Integer.MAX_VALUE
                        h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                    } catch( NumberFormatException nfe) {
                        // If the property cannot be parsed into an int, ignore it.
                    }
                }
                high = h;
    
                cache = new Integer[(high - low) + 1];
                int j = low;
                for(int k = 0; k < cache.length; k++)
                    cache[k] = new Integer(j++);
    
                // range [-128, 127] must be interned (JLS7 5.1.7)
                assert IntegerCache.high >= 127;
            }
    
    Integer i1 = new Integer(500);
    //        Integer i2 = new Integer(500);
    //        System.out.println(i1 == i2);//false
    //        System.out.println(i1.equals(i2));//true 已经重写了equals()来比较值
    //
    //        Integer i3 = Integer.valueOf(500);
    //        Integer i4 = Integer.valueOf(500);
    //        System.out.println(i3 == i4); //false
    //        System.out.println(i3.equals(i4));//true
    
            Integer i1 = new Integer(5);
            Integer i2 = new Integer(5);
            System.out.println(i1 == i2);//false
            System.out.println(i1.equals(i2));//true 已经重写了equals()来比较值
    
            //Interger.value()会复用-128到127范围内的数据————使用valueOf()更多一些
            Integer i3 = Integer.valueOf(5);
            Integer i4 = Integer.valueOf(5);
            System.out.println(i3 == i4); //true
            System.out.println(i3.equals(i4));//true
    
  • jdk1.5推出了一个新的特性:自动拆装箱。当编译器编译时若发现时基本类型与包装类型之间的相互赋值,则自动补齐代码完成转换工作,这个过程叫做自动拆装箱

    		//触发了一个自动装箱的特性,会被编译为:Integer i = Integer.valueOf(5);
            Integer i = 5;  //基本类型到包装类型---装箱
    
            //触发了自动拆箱的特性,会被编译为:int j = i.intValue();
            int j = i;//包装类型到基本类型---拆箱
    

补充

  1. 常见面试题:
    • ==和equals()的区别:
      • ==可以作用于基本类型和引用类型
        • ==作用于基本类型,是在比较值是否相同
        • ==作用于引用类型,实在比较地址是否相同
      • equals()只能作用于引用类型
        • 若没有重写equals(),则默认调用的是Object类的equals()来比较地址是否相同,若想比较对象的属性值是否相同,需要重写equals()方法。在java中String重写了equals()来比较字符串内容是否相同

10.27

集合

  1. 什么是集合

    • 集合和数组一样,可以保存一组数据,并且提供了操作集合元素的相关方法,使用更方便(与数组相比更方便不需要缩容扩容,但是数组效率更高)
  2. java集合框架中的相关接口:

    • java.util.Collection接口:是所有集合的顶层接口,封装了所有集合所共有的方法,下面有很多种实现类,因此我们可有更多的数据结构选择

      Object封装了所有类所共有的方法 Collection所有集合所共有的方法

    • Collection接口下还有两种常见的子接口:

      • java.util.List:线性表,是可以重复的集合,并且有序
      • java.util.Set:不可重复集合,大部分实现类是无序的
  3. Collection常用方法(集合中重写了Object的toString()方法)

    • add():向集合中添加一个元素,成功添加则返回true

    • size():返回当前集合的元素个数

    • isEmpty():判断当前集合是否为空集,当且仅当size()为0时返回true

    • clear():清空集合

      public class CollectionDemo {
          public static void main(String[] args) {
              Collection c = new ArrayList();
              c.add("one");
              c.add("two");
              c.add("three");
              c.add("four");
              c.add("five");
              //集合中重写了Object的toString()方法,格式如下:
              //[元素1.toString(), 元素2.toString(), 元素3.toString(), ......]
              System.out.println(c);
              System.out.println("size:"+c.size()); //5,输出集合的元素个数
              //isEmpty()判断集合是否是空集(size()为0表示为空集)
              System.out.println("是否是空集:"+c.isEmpty()); //false
      
              c.clear(); //清空集合
              System.out.println("集合已清空");
              System.out.println(c);
              System.out.println("size:"+c.size()); //0
              System.out.println("是否为空集:"+c.isEmpty()); //true
          }
      }
      
    • contains():判断集合是否包含给定元素

    • boolean remove():从集合中删除给定元素,成功删除则返回true。从当前集合中删除与给定元素equals比较为true的元素,若存在重复元素则只删除一次

      public class CollectionDemo {
          public static void main(String[] args) {
              Collection c = new ArrayList();
              c.add(new Point(1,2));
              c.add(new Point(3,4));
              c.add(new Point(5,6));
              c.add(new Point(7,8));
              c.add(new Point(9,0));
              c.add(new Point(1,2));
              System.out.println(c);
      
              Point p = new Point(1,2);
              /**
               * boolean contains(Object o)
               * 判断当前集合是否包含给定元素(o)
               * 判断依据是给定元素是否与集合元素存在equals比较为true的情况
               */
              boolean contains = c.contains(p);
              System.out.println("是否包含:"+contains);
      
              /**
               * boolean remove(Object o)
               * 从当前集合中删除与给定元素equals比较为true的元素
               * 若存在重复元素则只删除一次
               */
              c.remove(p);
              System.out.println(c);
      
      
              //集合中存放的是元素的引用
              Collection cc = new ArrayList();
              Point pp = new Point(1,2);
              cc.add(pp); //将pp添加到集合c中----将pp的引用装在了cc中
              System.out.println("pp:"+pp); //(1,2)
              System.out.println("cc:"+cc); //[(1,2)]
      
              pp.setX(100);
              System.out.println("pp:"+pp); //(100,2)
              System.out.println("cc:"+cc); //[(100,2)]
          }
      }
      
    • boolean addAll():将参数组定集合中的元素添加到当前集合中,添加后当前集合发生改变则返回true

    • boolean containsAll():判断当前集合中是否包含参数集合中的所有元素

    • boolean retainAll():只取交集

    • boolean removeAll():删交集取剩下

      public class CollectionOperDemo {
          public static void main(String[] args) {
              Collection c1 = new ArrayList();
              c1.add("java");
              c1.add("c++");
              c1.add(".net");
              System.out.println("c1:"+c1); //c1:[java, c++, .net]
      
              Collection c2 = new ArrayList();
              c2.add("android");
              c2.add("ios");
              c2.add("java");
              System.out.println("c2:"+c2); //c2:[android, ios, java]
      
              c1.addAll(c2); //将c2添加到c1中
              System.out.println("c1:"+c1); //c1:[java, c++, .net, android, ios, java]
              System.out.println("c2:"+c2); //c2:[android, ios, java]
      
              Collection c3 = new ArrayList();
              c3.add("c++");
              c3.add("android");
              c3.add("php");
              System.out.println("c3:"+c3); //c3:[c++, android, php]
      
              boolean contains = c1.containsAll(c3); //判断c1中是否包含c3中的所有元素
              System.out.println("包含所有:"+contains); //false
      
              //取交集,c1中仅保留c1与c3的共有元素,c3不变
              //c1.retainAll(c3);
              //System.out.println("c1:"+c1); //c1:[c++, android]
              //System.out.println("c3:"+c3); //c3:[c++, android, php]
      
              //删交集,将c1中与c3共有的元素删除,c3不变
              c1.removeAll(c3);
              System.out.println("c1:"+c1); //c1:[java, .net, ios, java]
              System.out.println("c3:"+c3); //c3:[c++, android, php]
      
          }
      }
      
  4. 集合的遍历:

    • Collection接口提供了统一的遍历集合的方式:迭代器模式。通过iterator()方法可以获取一个用于遍历当前集合元素的迭代器
    • java.util.Iterator接口:定义了迭代器遍历集合的相关操作,不同的集合都实现了用于遍历自身元素的迭代器实现类,但是我们无序记住他们的名字,从多态的角度把他们看成iterator即可
    • 迭代器遍历遵循的步骤为:问(hasNext())、取(next())、删(remove())
  5. 增强for循环/新循环:

    • jdk1.5时推出了一个新的特性:增强for循环,也称为新循环,让我们使用相同的语法遍历集合和数组

    • 语法:

      for(元素类型 变量名 : 集合或数组){循环体}
      
  6. 泛型:

    • jdk1.5时推出的一个新特性
    • 泛型也称为参数化类型,允许我们在使用一个类时,传入某个类型来规定其内部的属性、方法参数或返回值类型,使得我们使用时更方便
      • 泛型在集合中被广泛使用,用来指定集合中元素的类型
      • 若不指定泛型的具体类型,则默认Object
      • 若指定了泛型的具体类型,则获取泛型的具体值时,编译器会帮我们补充强转操作
    public class GenericDemo {
        public static void main(String[] args) {
            Collection<Point> c = new ArrayList<>();
            c.add(new Point(1,2));
            c.add(new Point(3,4));
            c.add(new Point(5,6));
            c.add(new Point(7,8));
    
            Iterator<Point> it = c.iterator();
            while(it.hasNext()){
                Point p = it.next();
                System.out.println(p);
            }
    
            for(Point p : c){
                System.out.println(p);
            }
    
            /*
            Collection<String> c = new ArrayList<>();
            c.add("one");
            c.add("two");
            c.add("three");
            c.add("four");
            c.add("five");
            //c.add(123); //编译错误,123的类型违背了集合c所指定的泛型的实际类型String
    
            //迭代器所指定的泛型应当与其遍历的集合的泛型一致
            Iterator<String> it = c.iterator();
            while(it.hasNext()){
                String str = it.next();
                System.out.println(str);
            }
            for(String str : c){
                System.out.println(str);
            }
            */
        }
    }
    
  7. 集合和数组的转换:

    • 集合转换为数组:Collection接口的toArray() 所以是对象.toArray()

      public class CollectionToArrayDemo {
          public static void main(String[] args) {
              Collection<String> c = new ArrayList<>();
              c.add("one");
              c.add("two");
              c.add("three");
              c.add("four");
              c.add("five");
              System.out.println(c); //[one, two, three, four, five]
              //若参数数组元素个数==集合元素个数,那就正常转换
              //若参数数组元素个数<集合元素个数,那就正常转换(按照集合大小给数组)
              //若参数数组元素个数>集合元素个数,那就正常转换,同时末尾被默认值
              String[] array = c.toArray(new String[6]);
              System.out.println(Arrays.toString(array));
      
          }
      }
      
    • 数组转换为集合:Arrays类的静态方法asList(),所以是Arrays.asList()

      public class ArrayToCollectionDemo {
          public static void main(String[] args) {
              String[] array = {"one","two","three","four","five"};
              System.out.println("array:"+Arrays.toString(array));
      
              //asList()方法会返回内部的ArrayList
              //该ArrayList内部直接引用给定数组array
              List<String> list = Arrays.asList(array);
              System.out.println("List: "+list);
      
              //对数组操作后,集合也会做相应的改变
              array[1] = "six";
              System.out.println("array:"+Arrays.toString(array));
              System.out.println("List: "+list);
      
              //对集合操作后,数组也会做相应的改变
              list.set(2,"seven"); //将下标2的元素修改为seven---明天详细讲
              System.out.println("array:"+Arrays.toString(array));
              System.out.println("List: "+list);
      
              //添加元素/删除元素相当于要往数组中加元素/减元素
              //而数组是定长的,不会自动扩容/缩容,因此会发生不支持操作的异常
              //list.add("!!!!!!"); //运行时发生不支持操作异常
          }
      }
      

10.28

List

  • List接口:

    • 继承自Collection接口,List集合是可重复集合,并且有序,并且提供了一套可以通过下标操作元素的方法

    • 常见的实现类:

      • java.util.ArrayList:内部使用数组实现,查询性能更好(直接下标查找物理地址),增删性能不太好

      • java.util.LinkedList:内部使用链表实现,查询性能不太好,首尾增删性能好

        在对集合操作的增删性能没有特别苛刻的要求时,通常选择ArrayList

  • List集合常见方法:

    • get():根据下标获取元素

    • set():将指定元素设置到指定位置 ,并返回被替换的元素(用时再接收)

    • 重载add():将指定元素添加到指定位置,理解为插入操作

    • 重载remove():删除并返回指定位置元素

    • subList(): 原集合修改之后,子集将不能再进行任何操作了,操作则发生并发修改异常,但是可以重新获取子集

      public class ListDemo {
          public static void main(String[] args) {
              List<String> list = new ArrayList<>();
              list.add("one");
              list.add("two");
              list.add("three");
              list.add("four");
              list.add("five");
              System.out.println("list:"+list); //[one, two, three, four, five]
      
              /**
               * E get(int index):
               * 获取指定下标所对应的元素
               */
              String e = list.get(2); //获取第3个元素
              System.out.println(e); //three
      
              for(int i=0;i<list.size();i++){
                  System.out.println(list.get(i));
              }
              for(String s : list){
                  System.out.println(s);
              }
              Iterator<String> it = list.iterator();
              while(it.hasNext()){
                  System.out.println(it.next());
              }
      
              System.out.println("-----------------------------");
      
              /*
                E set(int index,E e):
                将给定元素(e)设置到给定位置(index),返回被替换的元素
               */
              String old = list.set(2,"six"); //将下标为2的元素设置为six,返回原始元素
              //list.set(2,"six"); //常规用法
              System.out.println(old);  //three
              System.out.println("list:"+list); //[one, two, six, four, five]
      
              /**
               * void add(int index, E e):
               * 将给定元素e添加到index所指定的位置,相当于插入操作
               */
              list.add(3,"three"); //将three插入到下标3的位置
              System.out.println("list:"+list); //[one, two, six, three, four, five]
      
              /**
               * E remove(int index):
               * 删除指定位置元素,并返回该位置对应元素
               */
              String o = list.remove(2); //删除下标2的元素,并返回对应元素
              System.out.println(o); //six
              System.out.println("list:"+list); //[one, two, three, four, five]
      
          }
      }
      
      public class ListDemo2 {
          public static void main(String[] args) {
              List<Integer> list = new ArrayList<>();
              for(int i=0;i<10;i++){
                  list.add(i*10);
              }
              System.out.println("list:"+list); //[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
      
              List<Integer> subList = list.subList(3,8); //获取下标3到7的子集
              System.out.println("subList:"+subList); //[30, 40, 50, 60, 70]
      
              //将子集的每个元素扩大10倍
              for(int i=0;i<subList.size();i++) {
                  subList.set(i, subList.get(i) * 10);
              }	
              System.out.println("subList:"+subList); //[300, 400, 500, 600, 700]
              //注意:对子集的操作就是对原集合元素的操作
              System.out.println("list:"+list); //[0, 10, 20, 300, 400, 500, 600, 700, 80, 90]
      
              list.set(3,3000); //将下标为3的元素修改为3000
              System.out.println("list:"+list); //[0, 10, 20, 3000, 400, 500, 600, 700, 80, 90]
              System.out.println("subList:"+subList); //3000, 400, 500, 600, 700
      
              list.remove(0); //删除list中的第1个元素
              System.out.println("list:"+list); //[10, 20, 3000, 400, 500, 600, 700, 80, 90]
              //原集合修改之后,子集将不能再进行任何操作了,操作则发生并发修改异常,但是可以重新获取子集
              //System.out.println("subList:"+subList); //运行时并发修改发生异常
      
              /**
               * java.util.Collections为集合的工具类,包含了集合相关的静态方法
               */
              Collections.reverse(list); //反转list集合(元素真实改变了)
              System.out.println("lisi:"+list);
      
          }
      }
      
  • 集合的排序:

    • Collections为集合的工具类,里面定义了很多静态方法用于操作集合

      public class ListSortDemo {
          public static void main(String[] args) {
              List<Integer> list = new ArrayList<>();
              Random rand = new Random();
              for(int i=0;i<10;i++){
                  list.add(rand.nextInt(100));
              }
              System.out.println("list原始数据:"+list);
      
              Collections.sort(list); //对list集合进行自然排序(从小到大)
              System.out.println("list排序后数据:"+list);
      
              Collections.reverse(list); //反转list集合(数据已经变化了)
              System.out.println("list反转后:"+list);
          }
      }
      
    • Collections.sort(List list)方法:可以对list集合进行自然排序(从小到大)Collections.sort()方法要求List集合中的元素必须是可比较的,若不可比较则直接发生编译错误,不允许排序。判断是否可比较的标准为元素是否实现了java.util.Comparable接口。实际开发中,我们是不会让我们自己定义的类去实现Comparable接口,因为这对我们的程序有侵入性

    侵入性:当我们调用某个API功能时,其要求我们为其修改其它额外代码,这个现象称为侵入性。侵入性越强越不利于我们程序的后期维护

    • 建议使用重载的Collections.sort(List list,Comparator c)方法,可以通过Comparator来自定义比较规则

      对英文字符串排序时,会按首字母的ASCII码排序 若首字母相同,则比较第2个字符的ASCII码,以此类推

    • public class ListSortStringDemo {
          public static void main(String[] args) {
              List<String> list = new ArrayList<>();
              list.add("王克晶");
              list.add("传奇djflajfdl");
              list.add("苍松老师");
              System.out.println("list原始数据:"+list);
              Collections.sort(list, new Comparator<String>() {
                  /*
                    compare()方法用于定义o1和o2比较大小的规则,并用返回值表达大小关系
                    返回值实现的要求:-------不用纠结,去记下面的结论即可
                    1)如果返回值>0,则表达的是o1>o2
                    2)如果返回值<0,则表达的是o1<o2
                    3)如果返回值=0,则表达的是o1=o2
                    结论:
                      1)前面的(o1)-后面的(o2)-----------升序
                      2)后面的(o2)-前面的(o1)-----------降序
                   */
                  public int compare(String o1, String o2) {
                      return o1.length()-o2.length(); //升序
                      //return o2.length()-o1.length(); //降序
                  }
              });
              System.out.println("list排序后数据:"+list);
          } 
      

Set

  • 继承自Collection接口,元素是不可重复的,并且大部分都是无序的
  • 常见的实现类:java.util.HashSet()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值