集合框架(理论)

目录

一、集合

二、List

1.Vector

2.LinkedList

三、Set

1.HashSet

2.TreeSet 

四、Map


一、集合

集合和数组都为容器,有何不同?

  1. 数组虽为容器,但是数组的长度是固定的;集合长度是不固定的。
  2. 数组存储的是基本数据类型,集合存储的是对象(引用数据类型)。

集合特点:集合只存储对象,集合长度是可变的,集合可以存储不同类型的对象。

添加元素,参数类型为Object,以便接收任意类型对象。

集合中存储的都是对象的引用(地址)

打印集合名,eg:System.out.println(list);打印出来的是封装在[ ]之间,以“,”隔开的,已添加在集合中的对象内容。

常用集合分类图 

证实集合中存储的是对象的引用:

import java.util.ArrayList;
import java.util.List;

/**
 *
 * 证实集合中存储的是对象的引用
 */
public class Demo1 {
    public static void main(String[] args) {
        List<Student> list1=new ArrayList<>();
        List<Student> list2=new ArrayList<>();
        Student stu=new Student();
        list1.add(stu);
        list2.add(stu);
        
        for(Student s:list2){
            s.setId(10);
            s.setName("zhangsan");
        }

        for(Student s:list1){
            System.out.println(s.getId()+","+s.getName());
        }
    }
}

public class Student {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

相关基本操作:

添加元素:集合名.add();

删除元素:集合名.remove();

                  集合名.clear();//清空集合

判断长度:集合名.size();

判断元素:集合名.contains(元素);

                  集合名.isEmpty();//判断集合是否为空

取交集:集合1.retainAll(集合2)//集合1中只保留和集合2相同的部分

              集合1.removeAll(集合2)//集合1中只保留和集合2不同的部分

遍历集合:迭代器Iterator

1.
for(Iterator it=集合.iterator();it.hasNext();  ){
    System.out.println(it.next());
}

2.
Iterator it=集合.iterator();
while(集合.hasNext()){
    System.out.println(it.next());

}

二、List

特点:元素有序,元素可以重复,因为该集合体系有索引。

ArrayList——底层数据结构为数组结构;线程不安全

                      特点:查询快,增删慢

LinkedList——底层数据结构是链表结构;线程不安全

                        特点:查询慢,增删快

Vector——底层数据结构是数组结构;线程安全

                  特点:增删查询都比较慢(后被ArrayList代替)

List集合的特有方法( 凡是可以操作角标的方法都是List集合体系特有的方法)

增:add(index,element)

       addAll(index,Collection)

删:remove(index)

改:set(index,element)

查:get(index)

       subList(from,to)//获取角标from到to这段元素(包含前不包含尾)

       ListIterator();列表迭代器

//获取所有元素
for(int x=0;x<集合.size;x++){
    System.out.pritnln(集合.get(x));
}

并发访问:在迭代过程中,添加或删除元素,会引发并发修改异常

eg:在集合al中含有元素Java01,Java02,Java03;

Iterator it=al.iterator();

while(it.hasNext()){

            Object obj=it.next();

            if(obj.equals("java2")){

                         al.add("Java0005");

             }

              System.out.println(obj);进行判断

}

由上述示例可知:Iterator有局限性(在遍历过程中,只能进行判断,取出,移除 )。所以引出了列表迭代器(ListIterator,是Iterator的子接口,List特有的迭代器)。

在迭代时,不可以通过集合对象的方法操作集合中的元素,否则会引起并发修改异。只能使用迭代器的方法操作元素,可是Iterator的方法是有限的,只能对元素进行判断,取出,删除操作。如果想要其他操作(如添加,修改等),就需要使用其子接口ListIterator。

ListIterator的特有方法:hasPrevious()逆向遍历列表。

1.Vector

枚举是Vector特有的方法(其实枚举和迭代是一样的);

由于枚举的名称以及方法的名称都过于长。

Enumeration en=v.elements();//e为集合名称
while(en.hasMoreElements()){
    System.out.println(en.nextElement());
}

举例说明:

package listPackage;

import java.util.Enumeration;
import java.util.Vector;

public class Demo2 {
    public static void main(String[] args) {
        Vector<Student> v=new Vector<>();
        Student stu1=new Student(1,"zhangsan");
        Student stu2=new Student(2,"lisi");
        Student stu3=new Student(3,"wangwu");
        v.add(stu1);
        v.add(stu2);
        v.add(stu3);
        Enumeration en=v.elements();
        while(en.hasMoreElements()){
            System.out.println(en.nextElement());
        }
    }
}

public class Student {
    private int id;
    private String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

 输出:

Student{id=1, name='zhangsan'}
Student{id=2, name='lisi'}
Student{id=3, name='wangwu'}

2.LinkedList

  • 添加方法:

addFirst()//从链表集合的最前面添加进链表

addLast()//从链表集合的最后面添加进链表

  • 获取元素(不删除元素)

getFirst()//获取链表集合的第一个元素

getLast()//获取链表集合的最后一个元素

如果链表集合中没有元素,会出现NoSuchElementException

  • 获取元素(删除元素)

removeFirst()//返回链表集合的第一个元素(该元素会从链表中移除)

removeLast()//返回链表集合的最后一个元素(该元素会从链表中移除)

如果链表集合中没有元素,会出现NoSuchElementException

在JDK1.6出现了以上方法的替代方法:

  • 添加方法:

offerFirst()//从链表集合的最前面添加进链表

OfferLast()//从链表集合的最后面添加进链表

  • 获取元素(不删除元素)

peekFirst()//获取链表集合的第一个元素

peekLast()//获取链表集合的最后一个元素

如果链表集合中没有元素,会返回Null

  • 获取元素(删除元素)

pollFirst()//返回链表集合的第一个元素(该元素会从链表中移除)

pollLast()//返回链表集合的最后一个元素(该元素会从链表中移除)

如果链表集合中没有元素,会返回Null

遍历元素
while(!link.isEmpty()){
    System.out.println(link.getFirst())
}

利用LinkedList完成队列和堆栈的模拟:

https://blog.csdn.net/The_Best_Hacker/article/details/89954983 

 三、Set

特点:元素是无序的,存入与取出的顺序不一定一致,元素无重复。

HashSet——底层数据结构为哈希表;非线程安全

TreeSet——底层数据结构是二叉树;非线程安全

1.HashSet

HashSet中存入元素,保证元素的无重复,需要:

(1)重写hashCode()方法,改为自定义方法。因为HashSet存值是通过hash码开辟空间存的,所以改写的hashCode需返回同一个hash值。

如:
public int hashCode(){
    return name.hashCode()+age*11;
    //如果两元素哈希值不同,存入集合中; 若相同,调用equals方法,比较其内容是否相同,若相同则不存,            
    //若不同存入集合。  
}

(2)调用equals方法比较

public boolean equals(Object obj){
    if(!obj instanceof Person){
        return false;
    }
    Person p=(Person)obj;
    return this.name.equals(p.name)&&this.age==p.age;
}

举例:

package setPackage;

import java.util.HashSet;
import java.util.Set;

public class Demo1 {
    public static void main(String[] args) {
        Set<Student> set=new HashSet<>();
        Student stu1=new Student(1,"zhangsan");
        Student stu2=new Student(2,"lisi");
        Student stu3=new Student(3,"wangwu");
        Student stu4=new Student(1,"zhangsan");
        set.add(stu1);
        set.add(stu2);
        set.add(stu3);
        set.add(stu4);
        
        for(Student stu:set){
            System.out.println(stu.toString());
        }
    }
    
}


public class Student {
    private int id;
    private String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
    public int hashCode(){
        return id+name.hashCode();
    }
    
    public boolean equals(Object obj){
        if(!(obj instanceof Student)){
            return false;
        }
        Student stu=(Student)obj;
        return this.name.equals(stu.name)&&this.id==stu.id;
    }
}

 输出:

Student{id=2, name='lisi'}
Student{id=1, name='zhangsan'}
Student{id=3, name='wangwu'}

总结:

HashSet如何保证元素的唯一性?

HashSet是通过hashCode方法和equals方法完成的。

对于判断元素是否存在,依赖的是元素的hashCode和equals方法。

2.TreeSet 

可以对Set集合中的元素进行排序。注意:排序时,当主要条件相同时,一定要判断次要条件。TreeSet自身会除掉重复元素,不需要重写方法。

TreeSet排序的第一种方式(Compareable):让元素自身具备比较性。元素需要实现Comparable接口,覆盖CompareTo方法。这种方式也称为元素的自然排序或者叫做默认排序。

TreeSet排序的第二种方式(Comparator):当元素自身不具有比较性,或者具备的比较性不是做需要的。这时就需要让集合自身具备比较性(例如:Set<Student> set=new TreeSet<>(new MyComparator))。在集合初始化时,就有了比较方式。定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。定义一个类实现Comparator接口,覆盖compare方法。

当两种排序都存在的时候(按元素排序,按集合排序),以比较器Comparator为主。

例如:

package setPackage;

import java.util.Set;
import java.util.TreeSet;

public class Demo3 {
    public static void main(String[] args) {
        
        Set<Person> ts=new TreeSet<>(new MyCompare());
        Person t1=new Person(12,"zhangsan");
        Person t2=new Person(21,"lisi");
        Person t3=new Person(33,"wangwu");
        Person t4=new Person(14,"zhangsan");
        Person t5=new Person(12,"zhangsan");

        ts.add(t1);
        ts.add(t2);
        ts.add(t3);
        ts.add(t4);
        ts.add(t5);
        

        for(Person p:ts){
            System.out.println(p.toString());
        }

    }
}

package setPackage;


public class Person implements Comparable{
//排序方式,按照id的大小排序
    private int id;
    private String sname;

    public Person(int id, String sname) {
        this.id = id;
        this.sname = sname;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", sname='" + sname + '\'' +
                '}';
    }

    public int compareTo(Object obj){
        if(!(obj instanceof Person)){
            throw new RuntimeException("非人类信息");
        }
        Person stu=(Person)obj;
        if(this.id>stu.id){
            return 1;
        }
        if(this.id==stu.id){
            return this.sname.compareTo(stu.sname);
        }
        return -1;
    }
}

package setPackage;

import java.util.Comparator;

public class MyCompare implements Comparator {
//排序方式:按照人名的字母排序
    public int compare(Object obj1,Object obj2){
        
        if(!((obj1 instanceof Person)||(obj2 instanceof Person))){
            throw new RuntimeException("含有不属于人的信息");
        }
        Person t1=(Person)obj1;
        Person t2=(Person)obj2;
        
        int num=t1.getSname().compareTo(t2.getSname());
        if(num==0){
            return t1.getId()-t2.getId();
        }
        return num;
    }
}

输出:

Student{id=21, sname='lisi'}
Student{id=33, sname='wangwu'}
Student{id=12, sname='zhangsan'}
Student{id=14, sname='zhangsan'} 

具体示例见:https://blog.csdn.net/The_Best_Hacker/article/details/89970061

若要输出集合(怎样加进去,怎样输出来,即:先入先出)
public int compareTo(Object obj){
    return 1;
}
若要输出集合(先入后出)
public int compareTo(Object obj){
    return -1;
}

四、Map

Map集合:该集合存储键值对。一对一对的存,而且要保证键的唯一性。(键与值之间用=相连)。

HashTable——底层数据结构是哈希表,不可以存入null作为键值。(同步安全,效率低)

HashMap——底层数据结构是哈希表,可以存入null键和null值。(不同步不安全,效率高)

TreeMap——底层数据结构是二叉树,可以用于给Map中的键进行排序。(不同步不安全,效率高)

常用方法:

  • 1.添加

put(k,v):返回键对应的原来值,刚开始添加的时候,返回的是null,若是同一键值,则后添加的会覆盖原有的键值,并返回被覆盖的值

putAll(Map<? extends K,? extends Value>  m):向集合中添加元素,元素为集合类型

  • 2.删除

clear()//清空集合

remove(Object obj)//删除键对应的元素,若集合不存在key,则返回null

  • 3.判断

containsValue(Object value)//判断集合是否存在value

containsKey(Object key)//判断集合是否存在key

isEmpty()//判断集合是否为空

  • 4.获取

get(Object key)//可以通过get方法返回值判断一个值是否存在,通过返回null来判断。

size()//获取集合的大小,包含多少个元素

values()//返回的是一个包含所有value的集合

遍历集合

keySet:将map中所有键存入Set集合中,因为Set集合具备迭代器。

               Set<String> keySet=map.keySet();

               Iterator it=keySet.iterator();

               while(it.hasNext()){

                              System.out.println(map.get(it.next()));

               }

               Map集合的取出原理:将map集合转成set集合,再通过迭代器取出。

entrySet:将map集合的映射关系存入到Set集合,而这个关系的数据类型为Map.Entry

               Set<Map.Entry<String,String>> entrySet=map.entrySet();

               Iterator<Map.Entry<String,String>> it=entrySet.iterator();

               while(it.hasNext()){

                              Map.Entry<String,String>   me=it.next();

                              System.out.println(me.getKey()+"...."+me.getValue());

               }

               Map集合的取出原理:先获取Map.Entry关系,在通过Map.Entry中的getKey()和getValue()方法获取关系中的键和值。

举例:

package mapPackage;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Demo1 {
    public static void main(String[] args) {
        Map<Integer,String> map=new Hashtable<>();
        map.put(1,"我爱学习");
        map.put(2,"沉迷学习");
        map.put(3,"无法自拔");
        map.put(1,"学习爱我");
        
       /* //遍历集合:通过迭代器遍历
        Set<Integer> set=map.keySet();
        Iterator it=set.iterator();
        while(it.hasNext()){
            System.out.println(map.get(it.next()));
        }
        无法自拔
        沉迷学习
        学习爱我

        */
        
        //entrySet:将map集合的映射关系存入到Set集合,而这个关系的数据类型为Map.Entry
        Set<Map.Entry<Integer,String>> entry=map.entrySet();
        Iterator<Map.Entry<Integer,String>> it=entry.iterator();
        while(it.hasNext()){
            Map.Entry<Integer,String> me=it.next();
            System.out.println(me.getKey()+","+me.getValue());
        }
    }
}

 输出:

3,无法自拔
2,沉迷学习
1,学习爱我

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值