javaSE基础-03-集合

简介

  • 用来存放数据的集合
  • 长度可以改变
  • 能存放任意的对象
  • 长度随着元素的增加而增加
  • 集合当中只能存放引用数据类型,基本数据类型会自动装箱(把基本数据类型转为对象)

javaSE基础-03-集合_第1张图片

  • List可以添加重复元素,add方法的返回值都是true,所以一般不接收返回结果

  • set不可以添加重复元素,如果添加,add方法会返回false

Collection

常用方法

add() //添加元素
remove() //移除元素
clear() //清除集合
isEmpty() //是否为空
size() //集合长度

集合转数组

集合.toArray() //转为数组的方法

toArray方法会自动把集合中的元素向上转型为Object类型,所有取元素的时候还要把此时数组中的元素向下转型为本来的数据类型。

javaSE基础-03-集合_第2张图片

数组转集合

Arrays.asList(数组)  //数组转为集合
  • 转为的集合不能进行添加、删除元素,其他方法可用

  • 也不会把基本数据类型的数组转为集合,因为此时的集合会把整个基本类型数组当做一个对象存入集合中

  • 引用数据类型会转为集合

带all常用方法

addAll() //把一个集合中的所有元素添加到另一个集合中
removeAll() //删除两个集合的交集
containsAll() //判断集合是否全部包含另一集合
retainAll() //取两者的交集并赋给调用的集合,调用的集合改变,返回true,否则返回false

迭代器遍历集合

Iterator it = 集合.iterator(); //取出来的每一个元素都会自动提升为Object
while(it.hasNext()){
	System.out.println(it.next());
}

javaSE基础-03-集合_第3张图片

List

角标

  • list集合可以根据角标获取元素

    集合.add(index,"aaa");
    集合.get(index) //根据角标index获取元素
    

迭代删除元素

在迭代集合的过程中,不允许直接修改集合的结构,否则就会报并发修改异常的错误。

原因是集合的修改次数modCount与迭代器的修改次数expectedModCount不相同导致的

可以使用迭代器自带的remove方法删除

javaSE基础-03-集合_第4张图片

迭代添加元素

与迭代删除元素相同

ArrayList(数组)

ArrayList可以不断增加长度的原因:把原有的数据复制出来,再创建一个新的数组容量增加50%,把复制的数组放到新的数组中,旧的数组抛弃。

LinkedList(链表)

特有的方法:

addFirst()   //第一个位置添加元素
addLast()  //最后一个位置添加元素
removeFirst()  //移除第一个元素
removeLast()  //移除最后一个元素

Vector(数组)

很少使用。。。。

ArrayList的区别:Vector是加锁的(synchronized),更加安全

javaSE基础-03-集合_第5张图片

Set

  • set中存放的元素都是无序的,且没有重复元素

自定义对象相等判断

需要覆盖equals()和hashCode()判断

HashSet

LinkedHashSet

  • 底层使用链表实现,是Set集合中,唯一一个保证元素是怎么存怎么取的

TreeSet

  • 保证元素唯一
  • 会对添加的元素进行排序(数字大小 或 字母顺序 或汉字的unicode码
  • 添加的数据类型必须是同一类型

添加自定义对象

不能直接添加自定义对象

自定义对象的类必须实现Comparable接口,且覆盖里面的compareTo()方法

class Person implements Comparable<Person>{
	String name;
	int age;
    //返回值是0,只添加第一个元素
    //返回值是一个正数,都能添加到集合中,且顺序为添加时的顺序,根据二叉树,每一个都成为上一个的右孩子,读取时按照二叉树中序遍历
    //返回值是一个负数,都能添加到集合中,且顺序为添加时的倒序,根据二叉树,每一个都成为上一个的左孩子,读取时按照二叉树中序遍历
	@Override
	public it compareTo(Person obj){
		return 0;
		
	}
}

集合中自定义对象的排序问题

TreeSet<Person> set = new TreeSet<>();
set.add(new Person("张三"),20);
set.add(new Person("李四"),25);
set.add(new Person("王五"),22);
set.add(new Person("赵六"),21);
set.add(new Person("赵六1"),21); 
//重写compareTo()方法
public int compareTo(Person obj){
	int num = this.age - obj.age;
    //如果年龄相等就比较名字,不相等就根据年龄排序,排序方法根据二叉排序树,读取方式为二叉树的中序遍历
    
    return num == 0 ? this.name.compareTo(obj.name) : num;
} 

TreeSet比较器

  • 定义一个类实现接口comparator

  • 覆盖里面的方法

TreeSet<String> set = new TreeSet<String>(new CompareLength());
set.add("aaaaaaaaa");
set.add("z");
set.add("sfaf");
set.add("fssfs");


class CompareLength implements Comparator<String>{
    @Override
    public int compare(String str1,String str2){
        //按照字符串长度进行比较
        //比较方式可以自定义,有了这个便不会再按照TreeSet默认的比较方式进行比较了
        int length = str1.length() - str2.length();
        return length == 0 ? str1.compareTo(str2) : length;
    }
}

泛型

定义

  • 广泛通用的类型(一开始不知道是什么类型,使用的时候才知道是什么类型)

  • 代码模板中类型不确定,谁调用该段代码,谁就可以来指明这个类型

  • 定义两步

    • 1.在类名后面加上 (字母T可任意定义,但要与变量前面的保持一致)
    • 2.在变量前面加上一个T,即变量的类型
  • 创建对象的时候指明类型,但必须是引用数据类型

注意点

  • 集合中泛型前后类型要保持一致
  • 泛型没有继承
  • 泛型其实是一个语法塘

泛型类与泛型方法

  • 泛型类

    • 在类上面定义的,创建对象的时候要指明泛型的类型
    • 泛型类中,不能使用在静态方法上面(静态方法时属于类的,泛型是在创建对象的时候才能知道类型)
  • 泛型方法

    • 在方法上声明
    • 使用方法时,参数传递确定类型
    • 方法要想单独使用泛型,必须要有参数才有意义
    • 静态方法也可以使用泛型

泛型通配符

  • 不知道使用什么类型接收的时候,使用 ? 表示位置

  • 只用来作接收使用

    void test(List<?> list) {
    
    }
    

上限和下限

上限

//泛型的上限,用来限定元素的类型必须是指定的(Number)的子类(或者是该指定类型)
static void test(List<? extends Number> list)

下限

//泛型的下限,用来限定元素的类型必须是指定的(Number)的父类(或者是该指定类型)
static void test(List<? super Number> list)

泛型擦除

把有泛型的集合赋值给没有泛型的集合,泛型会被擦除

Map(映射关系)

Map如List和Set一样都是接口,不能直接创建对象

内部维护了两个集合,表示两个集合之间的映射关系

A集合元素不能重复(Set集合)为key

B集合元素可以重复(List)为Value

可以单独把Key或者Value全部取出来单独放在一个集合中

Map里面的元素是无序的

HashMap、LinkedHashMap、TreeMap(会对key进行排序)

常用方法

//如果key是第一次添加,会返回null,如果key不是第一次添加会替换掉value并返回原来的value
map.put(key,value); 
map.clear(); //清除功能
map.remove(key); //可以根据key值删除元素
map.size(); //返回键值对的数量
map.get(key); //根据key值返回value


//没有迭代器,不能进行快速遍历
//方式1.1
//取出所有的key存入set集合
Set<String> allKeys = map.keySet();
//取出每一个key对应的 value
Iterator<String> it = allKeys.iterator();
while(it.hasNext()) {
    //取出set集合中的每一个key值
    String key = it.next();
    Object val = map.get(key);
    System.out.println(key+"="+val)
}

//方式1.2
Set<String> allKeys = map.keySet();
for(String key : map.keySet()) {
      System.out.println(key+"="+val)
}

//方式2.1
//获取所有的key-value对象 --> entry对象
Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
//遍历每一个entry对象
Iterator<Entry<String,Integer>> it = entrySet.iterator();
while(it.hasNext()) {
    //取出每一个entry对象
   Entry<String,Integer> en = it.next();
    //取出entry对象的key
    String key = en.getKey();
    //取出entry对象的value
    Integer value = en.getValue();
    System.out.println(key+"="+value)
}

//方式2.2
Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
for( Entry<String,Integer> entry : entrySet){
       System.out.println(en.getKey()+"="+en.getValue())
}

自定义的对象

默认比较的也是对象的地址,就像ListSet一样

HashMap与HashTable异同

相同点:

  • 底层都是哈希算法
  • 都是双列集合

不同点:

  • HashMap线程不安全,效率高 1.2版本才有
  • HashTable线程安全,效率低 1.0之前就有
  • HashMap可以储存null
  • HashTable不能存储null

你可能感兴趣的:(编程语言,java,javase)