Java集合

LinkedList类

LinkedList与ArrayList不同,LinkedList是方便添加或删除的List。实际开发中对一个集合元素的添加和删除经常会涉及到首尾的操作。

  • LinkedList的特点是添加和删除块,但是查询慢。这是因为LinkedList是链表在添加和删除元素时,只需要修改上一个节点记录的地址值即可;而对于查询则需要遍历到要查询的元素为止。
  • ArrayList的特点是查询快,添加和删除慢。查询快是由于数组的索引支持,所以可以通过直接计算出元素的地址值,因此可以直接通过元素的地址值获取指定的元素;添加和删除慢是因为ArrayList在添加和删除元素时,在底层会先创建一个新数组,先需要堆数组原有的数组进行拷贝,其次在末尾进行添加或者删除元素。

LinkedList提供了大量首尾操作:

public void addFirst(E e);

public void addLast(E e);

public E getFirst();

public E getLast();

代码实例如下:

public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<String> list=new LinkedList<String>();

        //添加元素
        list.add("Jack");
        list.add("Rose");
        list.add("Trump");

        //获取元素
        String name=list.get(1);
        System.out.println("第二个元素:"+name);

        //返回集合的迭代器
        Iterator<String> it=list.iterator();
        //利用迭代器便利
        while(it.hasNext()){
            String thisName=it.next();
            System.out.println(thisName);
        }
        System.out.println("------------");

        //使用增强for循环便利
        for(String thisName:list){
            System.out.println(thisName);
        }

        System.out.println(list);
        //删除
        list.remove();   //默认删除第一个元素   也可以通过索引删除指定元素或者删除首尾元素
        System.out.println(list);
    }
}

运行结果:

第二个元素:Rose
Jack
Rose
Trump
------------
Jack
Rose
Trump
[Jack, Rose, Trump]
[Rose, Trump]

LinkedList可支持栈结构

当然Java也提供专门用于栈结构的类Stack

LinkedList对于栈结构提供了如下的方法:

push 压栈

pop 弹栈

peek 查询出即将要出栈的元素(栈顶元素),检查有没有要弹出的元素,当栈为空时就返回空值。

代码实例:

public class StackDemo {
    public static void main(String[] args) {
        LinkedList<String> stack = new LinkedList<String>();
        stack.push("Jack");
        stack.push("Rose");
        stack.push("Lisa");

        System.out.println(stack);

        //获取一个元素 此时,由于是栈结构 所以获取的是最后压栈的元素
        String popName=stack.pop(); //这里获取的是Lisa元素
        System.out.println(popName);

        System.out.println(stack);

        String peekName=stack.peek();
        System.out.println(peekName);

        //peek查看元素不会减少元素
        System.out.println(stack);

    }
}

运行结果:

[Lisa, Rose, Jack]
Lisa
[Rose, Jack]
Rose
[Rose, Jack]

注意这里输出栈时,是从栈顶到栈底依次输出

LinkedList可支持队列结构

LinkedList为支持队列元素提供了如下的方法:

offer 加入队列

poll 离开队列

peek 查询出即将要离开队列的元素(即队首元素),可检查有没有要离开队列的元素,当队列为空时返回空值null

代码实例:

public class QueueDemo {
    public static void main(String[] args) {
        LinkedList<String> queue = new LinkedList<String>();
        queue.offer("Jack");
        queue.offer("Rose");
        queue.offer("Lisa");

        System.out.println(queue);

        //获取队首元素
        String pollName=queue.poll();
        System.out.println(pollName);

        System.out.println(queue);

        String peekName=queue.peek();
        System.out.println(peekName);

        System.out.println(queue);

        //清空队列
        queue.remove();
        queue.remove();
        //检查是否还有要离开的元素
        String name=queue.peek();
        System.out.println(name);   //队列为空时  peek()返回的是空值null
    }
}

运行结果:

[Jack, Rose, Lisa]
Jack
[Rose, Lisa]
Rose
[Rose, Lisa]
null

HashSet类

HashSet是Set接口的子类,不包括重复相同的元素,并且是无序的,且提供索引,所以不能通过索引获取元素,只能通过迭代器访问数据

HashSet下还有子类LinkedHashSet,是可预测迭代顺序的Set的集合。

代码实例:

public class HashSetDemo {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("Jack");
        set.add("Lisa");
        set.add("Rose");
        set.add("Rose");

        System.out.println(set);   //输出是无序的

        //获取元素,只能迭代器
        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            String name = it.next();
            System.out.println(name);
        }
        System.out.println("============");
        //使用增强for遍历set集合
        for(String name:set){
            System.out.println(name);
        }
    }
}

运行结果:

[Rose, Jack, Lisa]
Rose
Jack
Lisa
============
Rose
Jack
Lisa

注意这里输出结果是无序的,还要记住不能通过索引来访问只能使用迭代器来访问数据

HashSet的简单应用:使用HashSet求一个字符串中一共有几个不重复的字母,区分大小写,比如a,A是算两个字符

public class HashSetDemo2 {
    public static void main(String[] args) {
        String s;
        System.out.println("请输入一个字符串:");
        Scanner scanner = new Scanner(System.in);
        s=scanner.nextLine();

        //创建HashSet集合
        HashSet<Character> set = new HashSet<>();

        //将字符串拆分成一个个单个字符
        char[] chars = s.toCharArray();

        for(char ch:chars){
            //判断是否是字母
            if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){
                set.add(ch);
            }
        }
        System.out.println("在该字符串中总共有"+set.size()+"个不重复的字母。");
    }
}

ArrayList中使用contains方法判断是否有重复元素

自定义类型Person是Object类的子类,所以Person具备equals方法,而contains方法会调用equals方法,依次与集合当中已经存在的Person对象比较。 当Person类没有重写equals方法时,直接使用Object类继承过来的equals方法,而该方法比较的是对象的地址值。当Person类重写equals方法后,就可以将比较规则由比较地址值改为比较属性值。

下面代码是没有重写equals的:

public class ArrayList_contains {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();
        Person jack = new Person("Jack", "18");
        Person rose = new Person("Rose", "22");

        Person p = new Person("Jack","18");

        list.add(jack);
        list.add(rose);
	//这里没有重写equals方法 所以比较的是地址值 因此返回的是False  若重写equals方法比较的是name和age的成员变量则返回true
        System.out.println(list.contains(p));  

    }
}

下面代码是Person类中重写equals方法:

@Override
    public boolean equals(Object obj) {
        Person p=(Person)obj;
        if(p.getName()==getName()&&p.getAge()==getAge()){
            return true;
        }
        return false;
    }

重写之后在运行上面代码会发现返回的结果是true。

HashSet判断元素唯一性准则

Set集合不能添加重复元素,那其添加方法在添加是判断是否有重复元素,那其判断规则是怎么样的呢???

HashSet集合由于是无序的,其判断唯一的依据是元素类型的hashCode与equals方法返回的结果。

规则如下:

把对象加入到HashSet时,它会先使用对象的hashCode值来判断对象加入的位置;

如果此位置上没有其他对象存在,则判断元素不同,可存入新对象。

如果此位置有对象存在,先判断新元素与集合内已经有的旧元素的HashCode值:如果不同,判断为是不同的对象,可存入新对象;如果相同,在判断equals比较结果,返回true相同,则不可存入新对象;返回是的false则仍然不同,即可存入新对象。

所以,使用HashSet存储自定义类型,如果没有重写该类的hashCode与equals方法,则判断重复时,使用的地址值,如果想通过内容比较元素是否相同,则需要重写该类的hashCode与equals方法。

hashCode方法重写规则:
将对象的各个属性值的hashCode相加即是整个对象的HashCode值。
如果是基本类型,类似int,则直接返回int值就是该属性的hash值;
如果是引用类型,类似String,就调用该成员变量的hashCode方法返回该成员变量的hash值。

这样可以根据对象的内容返回hashCode值,从而可以根据hashCode判断元素是否唯一。
但是由于一些“碰巧的”情况下,可能出现内容不同但hashCode相同的情况,为了避免这些情况,我们要加入一些干扰系数。
可是加入干扰系数后,仍会出现一些“碰巧”的情况,所以我们还要进行equals的二次判断。

重写hashCode方法代码如下:

@Override
public int hashCode() {
    int thisHashCode
    thisHashCode+=name.hashCode()*17;
    thisHashCode+=age.hashCode
    return thisHashCo
}

Java集合框架之总结&体系图

单列集合体系图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K9xDr7kG-1615558587998)(image.png)]

Collection:所有单列集合的直接或间接接口,其指定了所有集合应该具备的基本功能。
List:元素可重复,有序,带索引。
Set:元素不可重复,无序,没有索引。
ArrayList:底层是数组结构,ArrayList的出现代替了Vector,增删慢,查看快。
LinkedList:底层是链表结构,同事对元素的增删操作效率高。
HashSet:底层是哈希表结构。在不重复的基础上无序。
LinkedHashSet:底层是哈希表结构结合链表结构,在不重复的基础上可预测迭代顺序。

集合的常见使用

在设计集合的使用时,经常定义对应的接口类型。在使用时,通过多态的方式给接口变量赋值,用于提高程序扩展性。

如:定义方法public void method(List list){},在调用方法是依据需求,传入ArrayList或LinkedList的对象。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值