java基础总结一

基础总结–String和集合

一、关于String类的使用

字符创广泛应用在java编程中,在java中字符串属于对象,java提供了String类来创建和操作字符

  • 创建字符串:
String greeting="这是一个字符串";
//在代码中遇到字符串常量时,这里值是“这是一个字符串”,编译器会使用该值创建一个String对象
  • 注意String类是不可以改变的,多以一旦创建了String对象,那么它的值就无法改变—如需修改则可以使用StringBuffer或者StringBuilder

  • 字符串的长度:

    • String 类的一个访问器方法是 length() 方法,它返回字符串对象包含的字符数。

    • public class StringDemo {
          public static void main(String args[]) {
              String site = "www.haohaoxuexi.com";
              int len = site.length();
              System.out.println( "网址长度 : " + len );
         }
      }
      
  • 连接字符串:

    • String提供了两种方法连接两个字符串:

    • //1、一般使用+操作符来连接字符串
      "我的名字是"+"Runoob"
      
    • //2、string1.concat(string2);
      "我的名字是 ".concat("Runoob");
      
  • 创建格式化字符串:

    • 我们知道输出格式化数字可以使用 printf() 和 format() 方法。

      String 类使用静态方法 format() 返回一个String 对象而不是 PrintStream 对象。

      String 类的静态方法 format() 能用来创建可复用的格式化字符串,而不仅仅是用于一次打印输出。

    • System.out.printf("浮点型变量的值为 " +
                        "%f, 整型变量的值为 " +
                        " %d, 字符串变量的值为 " +
                        "is %s", floatVar, intVar, stringVar);
      

StringBuffer和StringBuilder

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

public class Test{
  public static void main(String args[]){
    StringBuffer sBuffer = new StringBuffer("网址:");
    sBuffer.append("www");
    sBuffer.append(".haohaoxuexi");
    sBuffer.append(".com");
    System.out.println(sBuffer);  
  }
}
  • 三者异同:

    • String:不可变的字符序列,底层使用char[]存储。final修饰;

      • //源码分析
        String str=new String();//new char[0];
        String str=new String("abc");//new char[]{'a','b','c'}
        
    • StringBuffer:可变的字符序列,线程安全,但是效率低下,底层使用char[]存储

      • //源码分析
        StringBuffer sb1=new StringBuffer();//char[] value=new char[16];底层创建了一个长度是16的数组
        sb1.append('a');//value[0]='a';
        sb1.append('b');//value[1]='b';
        --------------------------------
        StringBuffer sb2=new StringBuffer("abc");
        //char[] value=new char["abc".length()+16];
        
      • 扩容问题:如果要添加的数据底层数组盛不下,那就需要扩容底层的数组。

        ​ 默认情况下,扩容为原来容量的2倍+2,同时将原有的数组中的元素复制到新的数组中。

      • 开发中建议大家使用:StringBuffer(int capacity),指定数组的长度

      - 常用方法:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cnrYBwe2-1605928848100)(/Users/xuechao/Documents/笔记/java基础总结/img/StringBuffer.png)]

    • StringBuilder:可变的字符序列,jdk5.0新增的,线程不安全,效率高,底层使用char[]存储

    • 三者运行效率:StringBuilder > StringBuffe r > String

二、集合和数组

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QEIG3meq-1605928848103)(/Users/xuechao/Documents/笔记/java基础总结/img/java集合框架图.png)]

从上面的集合框架图可以看到,Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。

一、集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:

  • 接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
  • 实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
  • 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zQhbRtHR-1605928848105)(/Users/xuechao/Documents/笔记/java基础总结/img/集合框架体系.png)]

二、集合和数组的区别

三、常用集合分类:

1、Collection接口

无序性:不等于随机性,存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的

不可重复性:保证添加的元素按照equals()方法判断时,不能返回true,即:相同元素只能添加一个

Set接口
  • 实例存储的是无序的,不重复的数据

  • 检索效率低下,删除和插入效率高

  • 插入和删除不会引起元素位置的变化

  • Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法

  • HashSet:主要实现类

    • 实现了Set集合,实际为一个HashMap的实例,底层的数据结构采用哈希表
    • 元素无序且唯一
    • 线程不安全,效率高
    • 允许null值
    • 对集合的迭代次序没有任何保证

  • TreeSet:

    • 不能有重复的元素,有序的集合,它的作用是提供有序的Set集合
    • 向TreeSet中添加的数据,要求是相同类的对象
    • TreeSet的底层实际使用的存储容器就是TreeMap,底层数据结构采用二叉树(红黑树)
    • 元素唯一且已经排好序
    • TreeSet中的元素必须实现Comparable接口并重写compareTo()方法,TreeSet判断元素是否重复 、以及确定元素的顺序靠的都是这个方法
  • LinkedHashSet:HashSet的子类

    • 集合不重复,同时具有可预测的迭代顺序
    • 一个非线程安全的集合
    • 底层是链表和哈希表共同实现的,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性
    • 是set集合中唯一一个能保证怎么存就怎么取的集合对象、
List接口
  • 实例存储的是有序的,可以重复的元素

  • List和数组类似,可以动态的增长,根据实际存储的数据的长度自动增长List的长度

  • 查找元素效率高,插入删除效率低,因为会引起其他元素位置的改变

  • LinkedList:

    • 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。

    • LinkedList底层使用双向链表存储。

    • 线程不安全,效率高

    • 查询慢,增删快

    • 链表可分为单向链表和双向链表。

    • LinkedList 继承了 AbstractSequentialList 类。

    • LinkedList 实现了 Queue 接口,可作为队列使用。

    • LinkedList 实现了 List 接口,可进行列表的相关操作。

    • LinkedList 实现了 Deque 接口,可作为队列使用。

    • LinkedList 实现了 Cloneable 接口,可实现克隆。

    • LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输。

    • public class Test {
          public static void main(String[] args) {
              LinkedList<String> sites = new LinkedList<String>();
              sites.add("Google");
              sites.add("Runoob");
              sites.add("Taobao");
              sites.add("Weibo");
              System.out.println(sites);
            // 使用 addFirst() 在头部添加元素
              sites.addFirst("Wiki");
              System.out.println(sites);
             // 使用 addLast() 在尾部添加元素
              sites.addLast("Wiki");
              System.out.println(sites);
            // 使用 removeFirst() 移除头部元素
              sites.removeFirst();
              System.out.println(sites);
            // 使用 getFirst() 获取头部元素
              System.out.println(sites.getFirst());
          }
      }
      
  • ArrayList:

    • ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素,底层使用Object[]存储。

    • 查询快,增删慢

    • 线程不安全,效率高

    • 默认情况下:扩容为原来的1.5倍,同时需要将原有的数组复制到新的数组中

    • ArrayList 继承了 AbstractList ,并实现了 List 接口。

    • ArrayList<E> objectName =new ArrayList<>();  // 初始化
      //E: 泛型数据类型,用于设置 objectName 的数据类型,只能为引用数据类型。
      //objectName: 对象名。
      
    • ArrayList 是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。

    • public class Test {
          public static void main(String[] args) {
              ArrayList<String> sites = new ArrayList<String>();
              sites.add("Google");
              sites.add("Runoob");
              sites.add("Taobao");
              sites.add("Weibo");
              System.out.println(sites);
              System.out.println(sites.get(1));  // 
              sites.set(2, "Wiki"); // 第一个参数为索引位置,第二个为要修改的值
              System.out.println(sites);
              sites.remove(3); // 删除第四个元素
              System.out.println(sites);
              System.out.println(sites.size());//计算元素数量
            //迭代数组数列
              for (int i = 0; i < sites.size(); i++) {
                  System.out.println(sites.get(i));
          }
      }
      
  • Vector:

    • Vector 类实现了一个动态数组。和 ArrayList 很相似

    • Vector是线程安全的,但是效率低

    • 查询快,增删慢

    • 底层创建了长度为10的数组,在扩容方面,默认扩容为原来的数组长度的2倍

    • Vector 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况

    • //第一种构造方法创建一个默认的向量,默认大小为 10:
      Vector()
      //第二种构造方法创建指定大小的向量。
      Vector(int size) 
      //第三种构造方法创建指定大小的向量,并且增量用 incr 指定。增量表示向量每次增加的元素数目。
      Vector(int size,int incr)
      //第四种构造方法创建一个包含集合 c 元素的向量:
      Vector(Collection c)  
      
2、Map:

Map的结构理解:

  • Map中的key:无序的,不可重复的,使用Set存储所有的key

  • Map中的value:无序的,可重复的,使用collection存储所有的value

  • 一个键值对:kry-value构成一个Entry对象

  • Map中的entry:无序的、不可重复的,使用Set存储所有的entry

  • 遍历Map:

    通过:keySet、entrySet方法

    • public class Test {
          public static void main(String[] args) {
              Map<Integer,String>  map=new HashMap<>();
              map.put(1,"dashan");
              map.put(2,"2343");
              map.put(3,"sdsaa");
              Set k=map.keySet();
              Set e=map.entrySet();
              Collection<String> c=map.values();
              System.out.println(c);
              System.out.println(e);
              Iterator iterator = e.iterator();
              while (iterator.hasNext()){
                  System.out.println(iterator.next());
              }
          }
      }
      
HashMap:性能最好
  • HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。

  • HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,但是可以有无数个value值为null

  • 线程不安全,是异步的

  • HashMap 是无序的,即不会记录插入的顺序。

  • HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。

  • 扩容:是新建了一个HashMap的底层数组,而后调用transfer方法,将就HashMap的全部元素添加到新的HashMap中(要重新计算元素在新的数组中的索引位置),比较耗时的操作。

  • public class RunoobTest {
        public static void main(String[] args) {
            // 创建 HashMap 对象 Sites
            HashMap<Integer, String> Sites = new HashMap<Integer, String>();
            // 添加键值对
            Sites.put(1, "Google");
            Sites.put(2, "Runoob");
            Sites.put(3, "Taobao");
            Sites.put(4, "Zhihu");
            System.out.println(Sites);
          //迭代HashMap
            for (Integer i : Sites.keySet()) {
                System.out.println("key: " + i + " value: " + Sites.get(i));
          //使用 get(key) 方法来获取 key 对应的 value:
            System.out.println(Sites.get(3));
          //使用 remove(key) 方法来删除 key 对应的键值对(key-value)
            Sites.remove(4);
          //删除所有键值对(key-value)可以使用 clear 方法:
            Sites.clear();
        }
    }
    
  • LinkedHashMap:

    • 有序的,且默认为插入顺序
    • LinkedHashMap就是HashMap+双向链表
    • 迭代顺序与键值对的插入顺序一样
  • ConcurrentHashMap:

    • 线程安全,推荐使用
    • 线程安全是通过cas+synchronized+volatile来实现的
    • 锁是分段锁,所以它的性能相对来说是比较好的
HashTable:性能较差
  • 是同步的,加入了synchronized关键字,保证了线程安全,支持序列化
  • 基于哈希表实现,内部通过单链表解决
  • 不可以放入空值
TreeMap
  • 基于红黑树(是一种自平衡二叉查找树)
  • 线程不安全
  • 元素默认按照keys的自然排序排列
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值