java高级语法4:集合

集合

集合概念

1567991947768
集合只能存放对象,存放的是引用

我们平常应该用的实现类:

  • List->ArrayList
  • Set->HashSet
  • Map->HashMap

HashSet

1567992056976
不可重复,指的是hashcode是否相同,而不是equals是否相同

HashSet的底层原理可以看这篇文章:https://wiki.jikexueyuan.com/project/java-collection/hashset.html

对于 HashSet 而言,它是基于 HashMap 实现的,底层采用 HashMap 来保存元素

由于 HashMap 的 put() 方法添加 key-value 对时,当新放入 HashMap 的 Entry 中 key 与集合中原有 Entry 的 key 相同(hashCode()返回值相等,通过 equals 比较也返回 true),新添加的 Entry 的 value 会将覆盖原来 Entry 的 value(HashSet 中的 value 都是PRESENT),但 key 不会有任何改变,因此如果向 HashSet 中添加一个已经存在的元素时,新添加的集合元素将不会被放入 HashMap中,原来的元素也不会有任何改变,这也就满足了 Set 中元素不重复的特性。

1567992221218
set.size();//获取集合元素个数

如果想让集合只能存相同类型的对象:使用泛型

TreeSet

1567992867912
TreeSet默认是排序了的

1567992956447
1567993054869
如图,如果要在TreeSet中放入自定义类型的对象,则必须实现compare方法

使用TreeSet必须放入相同类型对象

迭代器

Set set=new HashSet();

Iterator it= set.iterator();

//迭代输出法一

while(it.hasNext()){

Systems.out.printLn(it.next());//注意,调用next()会使迭代器加一

}

//迭代输出法二:foreach法(注意虽然思想是foreach,但是代码中还是只有for没有each)

for(Object obj:set){//将set中的每一个值取出来,赋值给obj

? Systems.out.printLn(obj);

}

List

1567993183445
Listlist=new ArrayList();

add添加数据,addAll在指定的下标位置添加数据

1567993326834
Vector较老,现在基本不使用

Map

1567993380251
1567993402650
put(key,value);

https://blog.csdn.net/caisini_vc/article/details/52452498

Java中HashMap是利用“拉链法”处理HashCode的碰撞问题。在调用HashMap的put方法或get方法时,都会首先调用hashcode方法,去查找相关的key,当有冲突时,再调用equals方法。hashMap基于hasing原理,我们通过put和get方法存取对象。当我们将键值对传递给put方法时,他调用键对象的hashCode()方法来计算hashCode,然后找到bucket(哈希桶)位置来存储对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当碰撞发生了,对象将会存储在链表的下一个节点中。hashMap在每个链表节点存储键值对对象。当两个不同的键却有相同的hashCode时,他们会存储在同一个bucket位置的链表中。键对象的equals()来找到键值对。

根据key可以修改value或者移出键

  • 遍历Map——法一

    1. map.keySet//获取map所有key的集合
    2. map.valueSet

    通过map.KeySet来遍历:

    1567993687169

  • 遍历Map——法二

    1567993732356
    1567993808152
    1567993835597
    1567993916025
    一般使用map集合,不会使用过于复杂的对象做key

工具类Collections

1567994010092
1567994138719

泛型

1567994289746
1567994348047
1567994406644

  1. 泛型类

    1567994483121
    就是C++中的模板,但是使用上会方便一点

    1567994518857
    1567994564476
    泛型类中可以定义泛型变量

  2. 泛型接口

    1567994662536
    类也就因此变成了泛型类

  3. 泛型方法

    1567994741101
    在public之后跟上要定义的泛型,则可以在方法中的任何位置使用泛型了

    在静态方法中,不能使用类定义的泛型,只能使用该方法自己定义的泛型

泛型通配符

1567995192390
1567995206126
有限制的通配符可以为参数类型给出一些限制

第三个比较有用:只有实现了Comparable接口才能传入,这样方法内部就可以使用Comparable的方法而保证所有传入的对象都可以操作了

枚举

1567995385346
示例:

1567995564852
每一个枚举,都是调用了一次构造方法

使用“枚举类名.枚举”相当于调用了构造方法。但每次执行获得的都是相同对象:枚举类中的每个枚举都是单例的

1567995616953

这里要注意,在第一次调用枚举类时,其中所有的对象就已经被创建了!可以做一个简单的测试来证明:

enum TestEnum{
    A(1,'a'),
    B(2,'b'),
    C(3,'c');
    private final Integer number;
    private final Character thisChar;
    private TestEnum(Integer number,Character thisChar){
        this.number=number;
        this.thisChar=thisChar;
        System.out.println(this.number+"is created");
    }
    public void showInfo(){
        System.out.println(this.number+this.thisChar);
    }

}
    @Test
    public void enumTest(){
        TestEnum e=TestEnum.A;
        e.showInfo();

    }

输出是:

1is created
2is created
3is created
98

例如这里,调用Season.SPRING之后实际执行的是new Season("春天","春暖花开");,当然这是在

1567995756702
1567995804645

原文地址:https://www.cnblogs.com/jiading/p/12367923.html