Java集合

前提:所有集合继承Iterable的含义是所有集合都是可以迭代的

集合不能直接存放基本数据类型,也不能直接存储java对象,集合中存放的是Java对象的内存地址(引用)
集合在Java中本身就是一个对象

集合数组的区别:

在这里插入图片描述

1、java.util.Collection

Collection接口下的集合:可重复无下标

List(接口)集合:List集合存储元素特点是有序(存储顺序)可重复,有序是因为存储元素有下标,

Set(接口)(对应Map)集合:Set集合存储元素的特点是无序不可重复,无下标

SortedSet(接口)(对应SortedMap)集合:首先是无序不可重复,但集合中元素是可排序的

在这里插入图片描述
List和Set区别:
(1)、List,Set都是继承自Collection接口,Map则不是
(2)、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)
(3).Set和List对比:
Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
(4)、ArrayList与LinkedList的区别和适用场景
Arraylist:
优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。

LinkedList:
优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景
缺点:因为LinkedList要移动指针,所以查询操作性能比较低。
适用场景分析:
当需要对数据进行对此访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。
集合选用:
在这里插入图片描述

List接口

在这里插入图片描述

Collection公共有
/*
    1、Collection中存放什么元素
        使用泛型之前,可以存放Object所有子类(不能存基本数据类型,也不能存对象,存的是地址)
        使用泛型之后,只能存放某个具体的类型
    2、常用方法
        boolean add(Object e)//往集合添加元素
        int size();//获取集合中元素个数
        void clear();// 清空集合
        boolean isEmpty();//判断集合是否为空,空返回true
        boolean contians(Object obj)判断是否包含obj,包含返回true
        Object toArray();//转化成数组
add()//往集合加元素
 */

import java.util.ArrayList;
import java.util.Collection;

public class CollectionTest01 {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add(1200);//自动装箱 Integer x = new Integer(1200);
        c.add(3.14);
        c.add(new Object());
        c.add(true);//自动装箱
        /*System.out.println("集合中元素的个数"+c.size());
        c.clear();
        System.out.println("集合中元素的个数"+c.size());
        c.add("hello");//元素个数+1
        System.out.println("集合中元素的个数"+c.size());
        c.add("浩克");
        System.out.println(c.contains("浩克"));
        System.out.println(c.contains("浩克2"));
        System.out.println(c.isEmpty());
        */
        Object[] objs=c.toArray();
        for(int i=0;i<objs.length;i++){
            Object o=objs[i];
            System.out.println(o.toString());
        }
    }
}

迭代器
在执行 .next()方法时,指向下一个元素

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/*
    迭代
    Iterator有三个方法hasNext(),next(),remove(),主要是前两个
    迭代器:负责遍历/迭代集合中的元素。最初并没有指向第一个元素,而是指向第一个元素的前一个位置
	
 */
public class CollectionTest02 {
    public static void main(String[] args) {
        //以下的遍历方式/迭代方式,是所有Collection通用的一种方式
        //Map集合中不能使用。在所有Collection及其子类
        Collection c=new ArrayList();//后面的集合无所谓,主要看前面的Collection接口怎么遍历
        c.add("ad");
        c.add("qwe");
        c.add(100);
        c.add(3.14);
        c.add(new Object());
        //对集合c进行遍历
        //第一步:获取集合对象的迭代器Iterator
        Iterator it=c.iterator();
        //通过上面的迭代器对象开始迭代/遍历集合
        /*
        以下两个方法是迭代器对象的方法
        boolean hasNext();//如果仍有元素可以迭代,就返回true
        Object next();//返回迭代的下一个元素。迭代器会往下走一位i,并将指向的元素返回
         */
        boolean hasNext=it.hasNext();
        while(it.hasNext()) {
                Object obj = it.next();
                System.out.println(obj);
        }
    }
}

注:一旦集合内元素发生变化,需要重新获取迭代器
以下代码会出现ConcurrentModificationException异常

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionTest66 {
    public static void main(String[] args) {
        Collection c66=new ArrayList();
        Iterator it= c66.iterator();//在这个位置获取迭代器

        c66.add(10);
        c66.add(20);
        c66.add(30);

        //Iterator it= c66.iterator();

        while(it.hasNext()){
            Object obj=it.next();
            System.out.println(obj);
        }
    }
}

但是调用迭代器的remove()方法时不同

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

//迭代器也有remove方法,同时删除迭代器快照的元素和集合元素,保持迭代器和集合统一

public class CollectionTest66 {
    public static void main(String[] args) {
        Collection c66=new ArrayList();
        //Iterator it= c66.iterator();//在这个位置获取迭代器

        c66.add(10);
        c66.add(20);
        c66.add(30);

        Iterator it= c66.iterator();

        while(it.hasNext()){
            Object obj=it.next();
            //c66.remove(obj);直接删除,会出现异常。因为直接删除,没有和迭代器的快照统一
            it.remove();//删除迭代器指向的当前元素
            System.out.println(obj);
        }

        System.out.println(c66.size());//0
    }
}

contains方法 (Collection)

import java.util.ArrayList;
import java.util.Collection;

/*
研究contains方法
    boolean contains(Object o)//判断集合是否包含某个对象o,包含返回true,不包含返回false
 */
public class CollectionTest04 {
    public static void main(String[] args) {
        Collection c4 =new ArrayList();
        String s1=new String("asd");
        c4.add(s1);

        String s2=new String("zxc");

        System.out.println("当前元素个数"+c4.size());

        String s3=new String("asd");
        //System.out.println(s3.equals(s1));//true
        System.out.println(c4.contains(s3));//true,contains底层调用equals方法,栈里的s1和s3指向堆里两个String对象
                                            // 但这两个对象指向字符串常量区同一块地方
                                            //s3并未放入集合c4中,所以c4并不包含s3,但是由于调用String类equals方法
                                            //所以误认为s3是s1,(比的是内容)
    }
}

contains 续

import java.util.*;

public class CollectionTest05 {
    public static void main(String[] args) {
        Collection c5=new ArrayList();
        //创建用户对象
        User u1=new User("jack");
        User u2=new User("jack");
        c5.add(u1);
        //System.out.println(c5.contains(u2));//false,因为底层调equals方法,u1.equals(u2)
                                            //User类没有重写equals方法,所以调用Object的equals比较内存地址
        System.out.println(c5.contains(u2));//重写User的equals方法之后,返回true
        c5.add(u2);
    }
}

class User{
    private String name;
    public User(){}
    public User(String name){
        this.name=name;
    }

    @Override
    //只要姓名一样就表示同一个用户,不再比较内存地址
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(name, user.name);
    }

}

remove方法也会调用equals方法

/*
remove方法也会调用equals方法来找到要删除的对象,只删除一次
 */
import java.util.*;
public class CollectionTest06 {
    public static void main(String[] args) {
        Collection c6=new ArrayList();
        c6.add(new String("hello"));
        c6.add(new String("hello"));
        c6.add(new String("hello"));
        String s2="hello";
        c6.remove(s2);
        System.out.println(c6.size());//2,因为底层remove方法调用的equals方法
    }
}

以上为Collection共有

ArrayList特有
import java.util.*;
/*
ArrayList集合
1、默认初始容量为10 (底层先创建长度0,当添加第一个元素的时候,初始化容量为10)
2、底层是Object[]数组
3、构造方式new ArrayList();或new ArrayList(20);
4、优点:检索效率高
   缺点:随机增删效率低,无法存储大数据量(因为数组,难找空间)

注:add()方法在集合已经装满的时候调用,集合会扩容,增加量为原容量的50%(原容量右移1位)
    尽量少扩容,影响效率。
 */
public class ArrayListTest01 {
    public static void main(String[] args) {
        //三种构造方法
        //默认容量10
        List list1=new ArrayList();
        System.out.println(list1.size());//0,size()获取的是集合中当前元素个数,不是获取容量
        
        //指定容量20
        List list2=new ArrayList(20);
        System.out.println(list2.size());//0
        
        //其天集合转换构造ArrayList集合
        Collection c=new HashSet();
        c.add(100);
        List list3=new ArrayList(c);
    }
}
LinkedList
import java.util.LinkedList;
import java.util.*;
/*
1、有个first保存第一个node内存地址
   有个last保存最后一个node内存地址
2、无初始化容量,first和last都是null
3、非线程安全
优点:随即增删效率高,适用于大数据和频繁随机增删的情况
缺点:不能数学计算被查找元素内存地址,每次都要从头遍历,效率低

注:无论是LinkedList还是ArrayList,不用关心具体是哪一个集合
    因为要面向接口编程,调用接口中的方法
 */
public class LinkListTeswt01 {
    public static void main(String[] args) {
        List l1=new LinkedList<>();
        l1.add(100);
        l1.add(200);
        for(int i=0;i< l1.size();i++){
            System.out.println(l1.get(i));
        }
    }
}
Vector (线程安全,效率低较少使用)

底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素

有子类 Stack栈数据结构

泛型机制

*只在编译阶段起作用,运行阶段无用
使用好处:集合中存储的元素类型统一,集合中取出的元素是泛型指定的类型,不再需要向下转型。大多是业务中,集合元素是统一的。这种泛型被大家认可。

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

public class GenericTest {
    public static void main(String[] args) {
        //不使用泛型
        List l1=new ArrayList();
        //准备对象
        Cat c=new Cat();
        Bird b=new Bird();

        //添加到集合中
        l1.add(c);
        l1.add(b);

        //遍历
        Iterator it1=l1.iterator();
        while(it1.hasNext()){
            //需要向下转型
            Object obj=it1.next();
            //Animal a=it.next();报错,因为.next取出来的是Object类对象
            if(obj instanceof Animal){
                Animal a=(Animal)obj;
                a.move();
            }
        }

        //使用泛型之后List<Animal>之后,表示List集合中只允许存放Anim类的数据
        //用泛型来指定集合中存放的数据类型
        List<Animal> l2=new ArrayList<Animal>();
        //l2.add("asd");报错,因为“asd”不是Animal类对象
        l2.add(c);
        l2.add(b);
        //表示迭代器迭代的是Animal类型
        Iterator<Animal> it2=l2.iterator();//必须加<Animal>,这样it.next()出来的就是Animal类对象
        while(it2.hasNext()){
            //这里不再需要判断是不是Animal类型,**也不需要强制类型转换,可以直接调用
            Animal a=it2.next();
            a.move();
        }
    }
}

class Animal{
    public void move(){
        System.out.println("动物在移动");
    }
}

class Cat extends Animal{
    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}

class Bird extends Animal{
    public void fly(){
        System.out.println("鸟在飞行");
    }
}

泛型2–钻石表达式

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
JDK8之后引入了自动类型推断机制,又称为钻石表达式
 */
public class GenericTest2 {
    public static void main(String[] args) {
        //ArrayList<这里的类型会自动推断>
        List<Animal> l3= new ArrayList<>();
        l3.add(new Cat());
        l3.add(new Bird());
        //遍历
        Iterator<Animal> it=l3.iterator();
        while(it.hasNext()){
            Animal a=it.next();
            a.move();
        }
    }
}

泛型3–自定义泛型

public class GenericTest3<asdasdasdasd>{//< >内随便写,表示能使用泛型
    public void doSome(asdasdasdasd o){
        System.out.println(o);
    }

    public static void main(String[] args) {
        GenericTest3<String> gt =new GenericTest3<>();
        gt.doSome("aasd");		//doSome()传入的参数是上面规定的String类

        //类型不匹配
        //gt.doSome(100);
    }
}

通用泛型

创建类的时候规定泛型

public class VO<T>{
	private Integer total;
	private List<T> dataList;

}
Set接口

Set不保存重复的元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set接口不保证维护元素的次序。

HashSet

底层数据结构采用哈希表实现,元素无序且唯一,需要重写hashCode和equals()方法。

/*
HashSet
无序不可重复
实际放入HashMap的key部分

参照HashMap
 */
import java.util.HashSet;
import java.util.Set;
public class HashSetTest {
    public static void main(String[] args) {
        Set<String> strs=new HashSet<>();
        strs.add("hello3");
        strs.add("hello1");
        strs.add("hello2");
        strs.add("hello4");
        strs.add("hello1");
        //遍历
        for(String s:strs){
            System.out.println(s);//变得无序,且去掉重复
        }
    }
}

hello1
hello4
hello2
hello3

TreeSet

底层数据结构采用二叉树来实现,元素唯一且已经排好序;唯一性同样需要重写hashCode和equals()方法。

/*
实现SortedSets接口的实现类
无序不可重复
元素会自动按照大小顺序排序
称为可排序集合

参照TreeMap
 */
public class HashSetTest {
    public static void main(String[] args) {
        Set<String> strs=new TreeSet<>();
        strs.add("A");
        strs.add("B");
        strs.add("Z");
        strs.add("Y");
        strs.add("Z");
        strs.add("K");
        for(String s:strs){
            System.out.println(s);
        }
    }
}
输出:
A
B
K
Y
Z

2、java.util.Map

Map相对于Collection。Map为键值对形式。key=value,key不能重复。
Map集合以key和value的键值对方式存储
key和value都是引用数据类型
key和value都是存储对象的内存地址
key起主导地位,value是key的附属品
常用方法:
V put(K key,V value)//添加键值对
V get(Object key)//通过key获取value
void clear() //清空
boolean containsKey(Object key)//判断是否包含某个key
boolean containsValue(Object value)//判断是否包含某个value
boolean isEmpty()
V remove(Object key)/通过key删除键值对
int size() //获取键值对数量
Set keySet() //获取所有key,所有的key是个Set集合
Collection values() //获取所有value
Set<Map.Entry<K,V>> entrySet() //将Map集合转换成Set集合
以(key=value)的形式存储在Set集合
Set集合中元素类型是Map.Entry<K,V> (静态内部类)

public class MapTest {
    public static void main(String[] args) {
        //创建HashMap对象
        Map<Integer,String> map=new HashMap();
        //添加键值对
        map.put(1,"zhangsan");//1自动装箱
        map.put(2,"lisi");
        map.put(3,"wangwu");
        //通过key获取value
        String value=map.get(2);
        System.out.println(value);
        //获取键值对数量
        System.out.println("数量"+map.size());
        //通过可以删除
        map.remove(2);
        System.out.println("数量"+map.size());//2
        //判断是否包含某个key,contains方法底层调用equals方法比对
        //自定义的类需要重写equals方法
        System.out.println(map.containsKey(4));//false
        //判断是否包含某个value,contains方法底层调用equals方法比对
        System.out.println(map.containsValue("zhangsan"));//true
        //获取所有value
        Collection<String> values=map.values();
        for(String s:values){
            System.out.println(s);
        }
        //
        //清空
        map.clear();
        System.out.println("数量"+map.size());
    }
}

Map集合的遍历

/*
    1、获取所有key,通过key遍历value
    2、通过Set<Map.Entry<K,v>> entrySet()方法
 */
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapTest02 {
    public static void main(String[] args) {
        Map<Integer,String> map=new HashMap<>();
        map.put(1,"zhangsan");
        map.put(2,"lisi");
        map.put(3,"wangwu");
        map.put(4,"zhaoliu");

        /*第一种方式,获取所有key,通过key遍历value
        Set<Integer> keys=map.keySet();
        Iterator<Integer> it=keys.iterator();
        while(it.hasNext()){
            Integer key=it.next();
            //通过key获取value
            String value=map.get(key);
            System.out.println(key+"="+value);
        }
         */
        /*第一种方式foreach
        Set<Integer> keys=map.keySet();
        for(Integer key:keys){
            System.out.println(key+"="+map.get(key));
        }
         */

        /*第二种方法Set<Map.Entry<K,v>> entrySet()方法
        * 把Map集合全转化成Set集合
        * Set集合中元素类型是Map.Entry<Integer,String>
        */
        //返回Set集合
        Set<Map.Entry<Integer,String>> set=map.entrySet();
        //迭代器
        Iterator<Map.Entry<Integer,String>> it=set.iterator();
        while(it.hasNext()){
            Map.Entry<Integer,String> node=it.next();
            Integer key=node.getKey();
            String value=node.getValue();
            System.out.println(key+"="+value);
        }
        //也可以用foreach,效率高
        for(Map.Entry<Integer,String> node:set){
            System.out.println(node.getKey()+"="+node.getValue());
        }
    }
}
HashMap

1、底层是哈希表
2、主要掌握
map.get(k)
1)先调用k的hashCode()方法得出hash值,通过hash算法转换成数组下标。快速定位
2)如果这个位置什么都没有,则返回null;如果这个位置有单向链表,则拿key和单向链表的每一个节点equals
如果所有节点都返回false,那么get方法返回null,只要有一个节点的k和参数k相等,则这个节点的value
就是要找的value
map.put(k,v)
1)先将k,v封装进Node对象中
2)调用hashCode()方法得出hash值,通过哈希函数将hash值转化成下标,下表位置如果没有元素
就把Node添加进去,如果有链表,此时会拿key和链表上各node的key比较,如果没有相同的
就把这个新节点添加到链尾。如果有相同的,则用新节点的value"覆盖"旧节点的value
**因为要equals比较,所以需要重写equals()方法,要计算hash值,所以需要重写hashCode()方法
3、HashMap集合key部分特点:
无序:因为put()方法添加元素,不一定挂到那个下标下面
不可重复:put()方法的覆盖保证不覆盖
4、放在HashMap集合key部分的元素相当于是HashSet集合
HashSet集合中的元素也需要重写equals()和hashCode()方法
5、HashMap默认初始化容量是16,默认加载因子是0.75
加载因子是HashMap底层数组容量到达75%的时候扩容
6、HashMap初始化容量必须是2倍(扩容是左移位操作),为了达到散列均匀,提高HashMap存取效率
7、允许key为null,重复的null值的key对应的value也会覆盖

import java.util.Map;
import java.util.HashMap;
import java.util.Set;

public class HashMapTest {
    public static void main(String[] args) {
        Map<Integer,String> map=new HashMap<>();
        map.put(111,"zhangsan");
        map.put(222,"lisi");
        map.put(333,"wangwu");
        map.put(444,"zgaoliu");
        map.put(222,"king");

        System.out.println(map.size());//4,key重复的时候,后一次覆盖前一次

        //遍历
        Set<Map.Entry<Integer,String>> set =map.entrySet();
        for(Map.Entry<Integer,String> entry:set){
            //无序不重复
            System.out.println(entry.getKey()+"="+entry.getValue());
        }
    }
}

需要重写equals()和hashCode()方法

/*
重写equals()和hashCode()方法
如果equals()方法重写了,那么hashCode()方法也要重写
equals()方法如果返回值是true,那么hashCode()返回值也要相同
equals()和hashCode()直接用IDEA生成,“同时生成”
 */
import java.util.HashSet;
import java.util.Set;
public class HashMapTest02 {
    public static void main(String[] args) {
        Student s1=new Student("zhangsan");
        Student s2=new Student("zhangsan");
        //重写equals()之前
        //s1.equals(s2);//false
        //重写quals()之后
        s1.equals(s2);//true

        //hashCode重写之前,值不相同
        System.out.println("s1的hashcode="+s1.hashCode());
        System.out.println("s2的hashcode="+s2.hashCode());
        //s1.equals(s2)为true,表示是s1和s2相同,那么往HashSet中放只能放进去一个
        Set<Student> students=new HashSet<>();
        students.add(s1);
        students.add(s2);
        System.out.println(students.size());//2,与只能放进去一个相悖,所以需要重写hashCode方法
                                            //1,重写之后s1.hashCode()与s2.hashCode()相同

    }
}
import java.util.Objects;
public class Student {
    private String name;

    public Student() {
    }

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

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

    public String getName() {
        return name;
    }

    //equals()
    //hashCode()
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Student)) return false;
        Student student = (Student) o;
        return Objects.equals(getName(), student.getName());
    }
    @Override
    public int hashCode() {
        return Objects.hash(getName());
    }
}
Hashtable

和HashMap区别:
1、Hashtable的key和value都不能为null,HashMap的都可以
2、Hashtable的方法都带有synchronized,线程安全,但效率低
3、Hashtable和HashMap底层都是哈希表数据结构,Hashtable初始化容量是11,默认加载因子是0.75
扩容是原容量*2+1
子类;
Properties类

import java.util.Properties;
/*
掌握常用方法即可
Properties是Map集合,继承Hashtable。Properties的key和value都是String类型
Properties被称为属性对象
Properties是线程安全的
常用方法:
    存:setProperty(String key,String value)
    取:getProperty(String key)
 */
public class PropertiesTest {
    public static void main(String[] args) {
        Properties p = new Properties();
        //存
        p.setProperty("username", "root");
        p.setProperty("password", "123");
        //取
        String s1 = p.getProperty("username");
        String s2 = p.getProperty("password");
        System.out.println(s1);
        System.out.println(s2);
    }
}
TreeSet

TreeSet集合(继承Collection接口、Set接口、SortedSet接口)
1、底层实际是TreeMap,TreeMap集合底层是二叉树
2、放到TreeSet集合的元素实际是放到TreeMap集合的key部分
3、TreeSet集合中的元素 无序不可重复,但是会按照元素大小顺序自动排序,称为可排序集合

import java.util.TreeSet;
public class TreeSetTest {
    public static void main(String[] args) {
        TreeSet<String> ts=new TreeSet<>();
        ts.add("zhangsan");
        ts.add("lisi");
        ts.add("wangwu");
        ts.add("zhangliu");
        //遍历,输出升序
        for(String s:ts){
            System.out.println(s);
        }

        TreeSet<Integer> ts2=new TreeSet<>();
        ts2.add(100);
        ts2.add(500);
        ts2.add(300);
        //遍历,输出升序
        for(Integer i:ts2){
            System.out.println(i);
        }

    }
}

TreeSet对自定义类进行排序1

/*
以下程序对自定义类型无法排序
因为大小没有说明,会出现Exception in thread "main" java.lang.ClassCastException: class Person cannot be cast to class java.lang.Comparable (Person is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
	at java.base/java.util.TreeMap.compare(TreeMap.java:1563)
出现这个异常是因为没有实现java.lang.Comparable接口
 */
import java.util.TreeSet;
public class TreeSetTest02 {
    public static void main(String[] args) {
        Person p1=new Person(20);
        Person p2=new Person(22);
        Person p3=new Person(21);

        TreeSet<Person> persons=new TreeSet<>();
        persons.add(p1);
        persons.add(p2);
        persons.add(p3);

        //遍历
        for(Person p:persons){
            System.out.println(p);
        }
    }
}

class Person{
    int age;

    public Person(int age) {
        this.age = age;
    }

    public Person() {
    }

    //重写toString

    @Override
    public String toString() {
        return "Person" +
                "age=" + age;
    }
}
TreeSet对自定义类进行排序2
/*
以下程序可以对自定义类型排序
因为实现了Comparable接口,重写了compareTo()方法
 */
import java.util.TreeSet;
public class TreeSetTest02 {
    public static void main(String[] args) {
        Customer c1=new Customer(20);
        Customer c2=new Customer(22);
        Customer c3=new Customer(21);

        TreeSet<Customer> customers=new TreeSet<>();
        customers.add(c1);
        customers.add(c2);
        customers.add(c3);
        //遍历
        for(Customer p:customers){
            System.out.println(p);
        }
    }
}
//放在TreeSet中的元素需要实现java.lang.Comparable接口
//并且实现compareTo()方法,equals()方法可以不写
class Customer implements Comparable<Customer>{
    int age;
    public Customer(int age) {
        this.age = age;
    }
    public Customer() {
    }
    //重写toString
    @Override
    public String toString() {
        return "Customer" +
                "age=" + age;
    }
    //需要编写比较的逻辑和规则,k.compareTo(t.key)
    @Override
    /*compareTo的返回值
        返回=0,表示相同会覆盖
        返回>0,会在右子树找
        返回<0,会在左子树找
     */
    public int compareTo(Customer o) {//c1.compareTo(c2)
        //this就是c1,c就是c2
        int age1=this.age;
        int age2=o.age;
        /*
        if(age1==age2)return 0;
        if(age1<age2)return 1;
        else return -1;
        */
        //相当于写成
        return this.age-o.age;
        //降序return this.age-o.age;
    }
}
TreeSet集合中元素可排序的’第二种方法":比较器
import java.util.Comparator;
import java.util.TreeSet;
/*
使用比较器
 */
public class TreeSetTest04 {
    public static void main(String[] args) {
       //创建TreeSet集合的时候需要使用比较器
        TreeSet<Wugui> wuguis=new TreeSet<>(new WuguiComparator());
        wuguis.add(new Wugui(1000));
        wuguis.add(new Wugui(700));
        wuguis.add(new Wugui(800));

        for(Wugui w:wuguis){
            System.out.println(w);
        }
    }
}
//class Wugui implements Comparable{ 原来方法
class Wugui {
    int age;

    public Wugui(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Wugui{" +
                "age=" + age +
                '}';
    }
}
//单独编写比较器,比较器实现java.util.Comparator接口。
// 对比Comparable()方法是java.lang包下的
class WuguiComparator implements Comparator<Wugui>{
    @Override
    public int compare(Wugui o1, Wugui o2) {
        //指定比较规则
        return o1.age-o2.age;
    }
}

总结:Comparable和Comparator选择:
当比较规则不会发生改变的时候,或则比较规则只有一个的时候,选择Comparable接口
当比较规则有多个的时候,选择Comparator比较器,符合OCP原则

Collection工具类:Collections

java.util.Collection 集合接口
java.util.Collections 集合工具类
import java.util.;
/

Collections.sort( );排序,参数需要是List集合类型
*/
public class CoolectionsTest {
public static void main(String[] args) {
//ArratList原本不是线程安全的
List list=new ArrayList<>();
//变成线程安全的
Collections.synchronizedList(list);
list.add(“bac”);
list.add(“acb”);
list.add(“abc”);
//排序,自定义的类,需要先实现Comparable接口
//Collections.sort()的参数必须是List集合类型
Collections.sort(list);
for(String s:list){
System.out.println(s);
}
//如果对Set集合排序
Set set=new HashSet<>();
set.add(“king1”);
set.add(“king4”);
set.add(“king2”);
set.add(“king3”);
//将Set转化成ArrayList集合
List list1=new ArrayList<>(set);
//可以实现排序
Collections.sort(list1);
for(String s:list1){
System.out.println(s);
}
}
}

总结

ArrayList:底层是数组
LinkList:底层是双向链表
Vesctor:底层是数组,线程安全,效率较低
HashSet:底层是HashMap,实际放到HashMap集合的key部分
TreeSet:底层是TreeMap,实际是放到TreeMap集合的key部分
HashMap:底层是哈希表
Hashtable:底层是哈希表,线程安全,效率较低
Properties:继承的Hashtable,key和value只能存储String
TreeMap:底层是二叉树数据结构,TreeMap集合的key可以自动按照大小排序

掌握:
每个集合创建
向集合添加元素
从集合取出元素
遍历集合
主要的集合类:
ArrayList
LinkedList
HashSet:HashMap的key,存储在HashMap集合的key元素需要同时重写hashCode()和equals()方法
TreeSet
Hashmap
Properties
TreeMap

集合之间的转化
在new的时候,把原先的集合当作构造函数的参数传入
Map不能直接转Set,需要调Map.keySet()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值