Java基础(集合)

一、集合概述

集合:可以存储任意类型的对象,并且长度可变的类

集合类位与java.util包中

集合类的继承体系如下图。

二、Collection接口

Collection是所有单列集合的父接口,定义了单列集合通用的一些方法,常用方法如下图。

开发中基本使用其子接口。

三、List接口

3.1List接口简介

List接口继承自Collection接口。

List集合允许出现重复的元素,所有的元素以线性方式存储,可以通过索引访问集合中的指定元素,元素的存入顺序和取出顺序一致。

List集合常用特有方法如下图。

3.2ArrayList集合

ArrayList是List接口的一个实现类,内部封装了一个长度可变的数组对象。

ArrayList集合查找元素便捷,不适合增删操作。

eg.

import java.util.*;
public class Main{
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
//打印元素长度
        System.out.println(list.size());
//打印指定位置元素
        System.out.println(list.get(1));
    }
}

3.3LinkedList集合

LinkedList集合是List接口的另一个实现类,内部维护了一个双向循环链表。

LinkedList集合增删效率高。

LinkedList集合常用特有方法如下图。

eg.

import java.util.*;
public class Main{
    public static void main(String[] args){
        LinkedList list = new LinkedList();
        list.add(1);
        list.add(2);
        list.add(4);
//指定位置插入元素
        list.add(2,3);
//删除指定位置元素
        list.remove(2);
    }
}

3.4Iterator接口

Iterator接口也是集合中的一员,但主要用于迭代访问(遍历)Collection中的元素,因此Iterator对象也称为迭代器。

Iterator对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素。

遍历元素时,首先调用集合的iterator()方法获得迭代器对象,然后用hasNext()方法判断集合中是否存在下一个元素,如果存在则用next()方法取出元素,否则说明已到达集合末尾,停止遍历。

eg.

import java.util.*;
public class Main{
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        Iterator it = list.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
        }
    }
}

注意:集合在迭代器运行期间调用集合对象的remove()方法删除了元素,会导致迭代器预期的迭代次数发生改变,出现并发修改异常,如:

import java.util.*;
public class Main{
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        Iterator it = list.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            if(1.equals(obj)){
                list.remove(obj);   
            }
        }
    }
}

修改方式1:

import java.util.*;
public class Main{
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        Iterator it = list.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            if(1.equals(obj)){
                list.remove(obj);  
                break; 
            }
        }
    }
}

修改方式2:

import java.util.*;
public class Main{
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        Iterator it = list.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            if(1.equals(obj)){
                it.remove(obj);   
            }
        }
    }
}

因为调用迭代器对象的remove()方法删除元素所导致的迭代次数变化,对于迭代器对象本身来说是可预知的。

3.5foreach循环

foreach循环是一种更加简洁的for循环,也称增强for循环,用于遍历数组或集合中的元素,具体语法格式如下:

for(容器中元素类型 临时变量 : 容器变量){
    执行语句
}

eg.

import java.util.*;
public class Main{
    public static void main(String[] args){
        LinkedList list = new LinkedList();
        list.add(1);
        list.add(2);
        list.add(3);
        for(Object obj : list){
            System.out.println(obj);
        }
    }
}

注意:foreach循环遍历集合和数组时,只能访问集合中的元素,不能对其中的元素修改。

原因是只是将临时变量指向了一个新的变量,而与集合中的元素没有关系。

四、Set接口

4.1Set接口简介

Set接口继承自Collection接口,元素无序,并且都会以某种规则保证存入的元素不出现重复。

4.2HashSet集合

HashSet是Set接口的一个实现类,元素无序且不可重复。

HashSet存储元素的流程如下图。

如果存入的是自定义的类,应在定义类时重写hashCode()和equals()方法,否则不会去掉重复元素。

eg.

import java.util.HashSet;
class Student{
    String id;
    String name;
    public Student(String id, String name){
        this.id = id;
        this.name = name;
    }
//重写toString
    public String toString(){
        return id+":"+name;
    }
//重写hashCode
    public int hashCode(){
        return id.hashCode();//返回id属性的散列值
    }
//重写equals
    public boolean equals(Object obj){
        if(this == obj){return true;}//如果是同一个对象则直接返回true
        if(!(obj instanceOf Student)){return flase;}//判断对象是否为Student类型
        Student stu = (Student) obj;//强制转换为Student类型
        boolean b = this.id.equals(stu.id);//判断id值是否相等
        return b;
    }
}
public class Main{
    public static void main(String[] args){
        HashSet hs = new HashSet();
        Student stu1 = new Student("1","z");
        Student stu2 = new Student("2","l");
        Student stu3 = new Student("2","l");
        hs.add(stu1);
        hs.add(stu2);
        hs.add(stu3);
        System.out.println(hs);//输出只有前两个
    }
}

如果想让元素存储顺序一致,可以使用LinkedHashSet类,他也使用了双向链表。

4.3TreeSet集合

TreeSet可以对HashSet中的元素进行排序。

原因是因为元素的类可以实现Comparable接口,该接口强行对实现它的每个类的对象进行整体排序,这种排序被称为类的自然排序。该接口的compareTo()方法称为自然比较方法。

自定义对象必须实现Comparable接口并重写compareTo()方法实现对象元素的顺序存取。

eg.

import java.util.TreeSet;
class Student{
    String id;
    String name;
    public Student(String id, String name){
        this.id = id;
        this.name = name;
    }
//重写toString
    public String toString(){
        return id+":"+name;
    }
    @Override
    public int compareTo(Student o){
        return 0;//集合中只有一个元素
        //return 1;//怎么存就怎么取
        //return -1;//倒序取
    }
}
public class Main{
    public static void main(String[] args){
        TreeSet ts = new TreeSet();
        Student stu1 = new Student("1","z");
        Student stu2 = new Student("2","l");
        Student stu3 = new Student("2","l");
        ts.add(stu1);
        ts.add(stu2);
        ts.add(stu3);
        System.out.println(hs);
    }
}

除了自然排序,还有比较器排序。即实现Comparator接口,重写compare()方法。

eg.

import java.util.Comparator;
import java.util.TreeSet;
class Student{
    String id;
    String name;
    public Student(String id, String name){
        this.id = id;
        this.name = name;
    }
//重写toString
    public String toString(){
        return id+":"+name;
    }
}
public class Main{
    public static void main(String[] args){
        TreeSet ts = new TreeSet(new Comparator(){
            @Override
            public int compare (Object obj1, Object obj2){
                return 0;
            }    
        );
        Student stu1 = new Student("1","z");
        Student stu2 = new Student("2","l");
        Student stu3 = new Student("2","l");
        ts.add(stu1);
        ts.add(stu2);
        ts.add(stu3);
        System.out.println(hs);
    }
}

五、Map接口

5.1Map接口简介

Map接口是一种双列集合,每个元素都包含一个键值对,键和值之间存在的对应关系称为映射。

常用方法:

5.2HashMap集合

HashMap没有重复的键且键值无序。如果存入已存在的键,新的值会覆盖原来的值。

eg.遍历键值对方法

import java.util.*;
public class Main{
    public static void main(String[] args){
        HashMap map = new HashMap();
        map.put("1","a");    
        map.put("2","b"); 
        map.put("3","c");
        Set entrySet = map.entrySet();
        Iterator it = entrySet.iterator();
        while(it.hasNext()){
            Map.Entry entry = (Map.Entry)(it.next());
            Object key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(key+":"+value);
        }   
    }
}

5.3TreeMap集合

Map接口提供了一个可以对集合中元素键值进行排序的类TreeMap。

键必须唯一。

TreeMap也分为自然排序和比较排序。

5.4Properties集合

Map接口中的实现类HashTable与HashMap类似,但前者线程安全。

HashTable存取元素速度很慢,目前已被取代,但子类Properties有用。

Properties主要用来存储字符串的键和值,实际开发中用来存取应用的配置项。

eg.

import java.util.*;
public class Main{
    public static void main(String[] args){
        Properties p = new Properties();
        p.setProperty("Background-color","red");
        p.setProperty("Font-size","14px");
        Enumeration names = p.propertyNames();//获取Enumeration对象所有键的枚举
        while(names.hasMoreElements()){
            String key = (String) names.nextElement();
            String value = p.getProperty(key);
            System.out.println(key+"="+value);
        }
        
    }
    
}

六、泛型

6.1泛型概述

泛型是程序设计语言的一种特性。允许程序员在使用强类型程序设计语言编写代码时定义一些可变部分,这些可变部分在运行前必须指明。

在编程中用泛型代替某个实际的类型,而后通过实际调用时传入或推导的类型来对泛型进行替换,达到代码复用。

6.2泛型类和泛型对象

泛型类是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值和参数类型。

import java.util.*;
public class Main{
    public static void main(String[] args){
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        for(Integer str : list){
            System.out.prinln(str);
        }
    }
}

6.3泛型方法

泛型方法所在的类是不是泛型类都可以。

import java.util.*;
public class Main{
    public static void main(String[] args){
        Dog dog = new Dog();
        dog.show("hello");
        dog.show(1);
        dog.show(0.5);
    }
}
class Dog{
    String eat;
    Integer age;
    public <T> void show(T t){
        System.out.println(t);
    }       
}

6.4泛型接口

泛型接口的定义

interface Infor<T>{
    public T getVar();
} 

定义泛型接口的子类有两种方式:

1.在子类实现的接口中明确给出泛型类型;

2.直接在子类后声明泛型。

6.5类型通配符

Java中集合不能协变,即List<Animal>不是List<Dog>的父类。

为了解决这个问题,Java泛型提供了类型通配符?。

eg.

import java.util.*;
public class Main{
    public static void main(String[] args){
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        test(list);
    }
    public static void test(List<?> list){
        for(int i = 0;i<list.size();i++){
            System.out.println(list.get(i));
        }
    }
}

注意,如果使用了通配符“?”接受泛型对象,则该对象只能被接受不能修改。

七、JDK8新特性——Lambda表达式

Lambda表达式可以取代大部分的匿名内部类,在集合的便利和其它集合的操作中优化代码结构。

Lambda表达式由参数列表、箭头符号->和函数体构成。函数体既可以是一个表达式,也可以是一个语句块。

常用的语法格式如下表。

  • 14
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值