java第三周(基础完结)

day12-集合框架(上)

  • 集合入门

  • Collection接口

  • List

  • Set

  • Map

集合入门

集合(Conllection),集合即一种容器,是数据结构在Java应用中的 一种体现,早在jdk1.0的版本中就存在一些集合相关类:Stack,Properties,Vector,Dictionary;但是由于上述结构均为类,不利于扩展,并且无统一标准;因此,在JDK1.2之后Java就引入了集合框架,其中包括Collection,List,Set,Deque(JDK1.6),Map等接口.

Collection

Collection是集合框架的顶层接口,大多数的集合类,接口都是直接或者间接从Collection继承或者实现

List接口

List接口直接从Collection接口继承而来,List集合是一个有序集合(元素在集合中的存储顺序是有序的,获取的时候根据存储的位置获取),List允许重复元素,List接口包含三个比较常用的实现类:ArrayList、LinkedList、Vector(jdk1.0)

public static void main(String[] args) {
        
        List list = new ArrayList();
//      List list = new LinkedList();
//      List list = new Vector();
        
        list.add(new String("abc"));
        list.add("hello");
        list.add(123);
        list.add(new User());
        //向指定的索引处插入元素
        list.add(1, true);
        //替换指定 索引出的元素
        list.set(1, true);
        
        //移除指定索引处的元素,并返回该被移除的元素对象
//      Object obj = list.remove(1);
//      boolean  result = list.remove(new String("abc"));
//      System.out.println(result);
        
        
        List list2 = new ArrayList();
        list2.add(123);
        list2.add("hello");
        
        //从当前集合中删除子集
        boolean result = list.removeAll(list2);
        System.out.println(result);
        System.out.println(list);
        
        //向当前集合添加子集合
        list.addAll(list2);
        
        System.out.println(list);
    }

ArrayList,LinkedList,Vector区别?

ArrayList基于可变长度的数组实现,内部通过数组拷贝原理实现容量扩展,ArrayList每次扩展为源数组的一半,ArrayList进行元素查询时相对LinkedList快(每个元素都有一个索引,可以直接根据索引获取元素),ArrayList是线程不同步的实现(效率高,不安全)

LinkedList基于链表的实现,内部元素之间通过首尾指针关联,在进行元素修改时(比如新增元素),相对ArrayList会更方便(只需要修改元素的首尾指针指向即可),但是在进行查询时链表的查询效率是低于数组的

Vector基于可变长度的数组实现,Vector每次扩展为原来长度的一倍(ArrayList是一半),Vector是线程同步的实现(效率低,安全)

Set集合

Set集合也是从Collection接口继承而来,set集合是一个无序集合(存储顺序与元素的添加顺序无关),set集合不允许出现重复元素(重复元素会覆盖第一次出现的元素),不允许存在e1.equals(e2)的情况(针对HashSet的实现),set集合中的元素无法通过索引获取;Set集合有两个常用的实现类:HashSet、TreeSet

基于HashSet的实现

public static void main(String[] args) {
        
        Set set = new HashSet();
        set.add("hello");
        set.add("rose");
        set.add("jack");
        set.add("admin");
        set.add("true");
        set.add("admin");
​
//      for (Object o : set) {
//          System.out.println(o);
//      }
        Iterator it = set.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }

基于TreeSet的实现

首先被作为元素的对象必须实现Comparable接口并实现接口中的compareTo方法

public class Student implements Comparable<Student>{
​
    private int age;
    
    public Student(int age) {
        this.age = age;
    }
    //实现对比方法
    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }
​
    @Override
    public String toString() {
        return "Student [age=" + age + "]";
    }
​
}

测试类:

public class TreeSetDemo {
​
    public static void main(String[] args) {
        Set set = new TreeSet();
//      set.add(10);
//      set.add(20);
        set.add(new Student(28));
        set.add(new Student(16));
        set.add(new Student(18));
        set.add(new Student(18));
//      set.add(new String("hello"));//ClassCastException
        System.out.println(set);
​
    }
​
}

HashSet和TreeSet区别?

HashSet元素添加到集合中之后,元素的存储顺序,基于散列算法(计算获取对象在内存中的唯一地址)实现的元素排序,HashSet是线程不同步的实现;

TreeSet基于二叉树中红黑树算法实现,TreeSet内部的元素存储顺序跟元素实现的Comparable接口中compareTo方法有关,所以TreeSet要求所有元素所对应的类必须实现Comparable接口(TreeSet要求内部存储的元素必须是相同的数据类型),TreeSet也是线程不同步的实现;

Map集合

Map集合是一种键值对结构,不同与List与Set;Map集合中的元素通常由key-value构成,一个键可以指向一个值,但是键不允许重复,但是值可以,Map集合的出现是为了取代老式的Dictionary类,Map集合常用的两个实现类:HashMap,TreeMap

public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<>();
        map.put("一号", 100);
        map.put("二号", 100);
        map.put("三号", 80);
        map.put("四号", 70);
        map.put("五号", 60);
        
        System.out.println(map);
        //获取map集合中的所有键集
        Set<String> keys = map.keySet();
        //获取map集合的值集
        Collection<Integer> c = map.values();
        
        for(String k:keys){
            //根据键获取值
            int i = map.get(k);
            System.out.println(k+":"+i);
        }
    }

HashMap、TreeMap、Hashtable,ConcurrentHashMap的区别

HashMap基于散列表实现的Map(jdk1.2)接口,内部的元素存储顺序根据元素中键的Hash值排序,每个元素都存在一个独一无二的hash地址,所以不允许出现重复的键,允许空键值,此实现是线程不同步的。

TreeMap基于红黑树的实现,内的元素存储顺序默认按照元素的自然顺序排序,或者根据给定的比较器(Comparator)进行排序,集合中键必须是同一种数据类型,键对应的类型必须实现Comparable接口,并实现比较的方法(compareTo(T t))

Hashtable基于散列表的从老式Dictionary(jdk1.0)类继承,Hashtable不允许空键值存在,Hashtable是线程安全的实现(线程同步)

哈希算法:

https://blog.csdn.net/asdzheng/article/details/70226007

完成一个通讯录需求:1.添加联系人(联系人:编号,姓名,电话,QQ)2.联系人查询(输入姓名或电话查询)3.显示联系人列表(要求按照姓名拼音字典顺序排序:中文排序)4.根据编号删除指定联系人

Jsoup 爬虫插件

day13-集合框架(下)

  • Collections类

  • Comparable(内部比较器)&Comparator(外部比较器)

  • 泛型(Generic)

  • *集合流式处理(JDK8+)

Collections类

jdk1.2引入集合框架后,同时也新增了一些类用于方便的对集合进行处理(排序,查找等),这些功能主要包含在java.util.Collections类中,Collections类中的所有方法都是静态方法,所以调用起来比较简单

public class CollectionsDemo {
​
    public static void main(String[] args) {
​
        List<User> list = new ArrayList<User>() {
            {
                add(new User("james", 22));
                add(new User("tom", 28));
                add(new User("kobe", 62));
                add(new User("curry", 19));
                add(new User("wade", 55));
                add(new User("rose", 42));
                add(new User("zhangsanfeng", 42));
​
            }
        };
​
        // 获取集合中最大(根据元素自然顺序-Comparable接口中compareTo方法的实现)的元素
        User max = Collections.max(list);
        // 若集合中的元素未实现Comparable接口时,可以单独使用比较器(Comparator)比较 Lambda表达式
        max = Collections.max(list, (u1, u2) -> u1.getAge() - u2.getAge());
        System.out.println(max);
​
        // 反转集合
        Collections.reverse(list);
        // 对集合顺序随机打乱(洗牌)
        Collections.shuffle(list);
​
        // 排序,根据集合中元素实现的Comparable接口
        Collections.sort(list);
        // 根据提供的比较器排序
        Collections.sort(list, (u1, u2) -> u1.getAge() - u2.getAge());
​
        for (User user : list) {
            System.out.println(user);
        }
    }
}

泛型

jdk1.5之后新增参数化类型,即将一个类型作为参数进行传递,这样可以将类型检查提前到编译期间,从而避免了在运行时进行类型检查(造成编程困难),具体使用如下 :

BaseManager.java

//设置参数化类型
public interface BaseManager<T> {
​
    public boolean add(T obj);
    
    public boolean del(T obj);
    
    public boolean update(T obj);
    
    public T findOne(T obj);
    
    public List<T> findAll();
    
}

DeptImpl.java

public class DeptImpl implements BaseManager<Dept>{
​
    @Override
    public boolean add(Dept obj) {
        // TODO Auto-generated method stub
        return false;
    }
​
    @Override
    public boolean del(Dept obj) {
        // TODO Auto-generated method stub
        return false;
    }
​
    @Override
    public boolean update(Dept obj) {
        // TODO Auto-generated method stub
        return false;
    }
​
    @Override
    public Dept findOne(Dept obj) {
        // TODO Auto-generated method stub
        return null;
    }
​
    @Override
    public List<Dept> findAll() {
        // TODO Auto-generated method stub
        return null;
    }
}

EmpImpl.java

public class EmpImpl implements BaseManager<Emp> {
​
    @Override
    public boolean add(Emp obj) {
        // TODO Auto-generated method stub
        return false;
    }
​
    @Override
    public boolean del(Emp obj) {
        // TODO Auto-generated method stub
        return false;
    }
​
    @Override
    public boolean update(Emp obj) {
        // TODO Auto-generated method stub
        return false;
    }
​
    @Override
    public Emp findOne(Emp obj) {
        // TODO Auto-generated method stub
        return null;
    }
​
    @Override
    public List<Emp> findAll() {
        // TODO Auto-generated method stub
        return null;
    }
}

对于以上如果有多个参数化类型可以在声明时指定:

public interface BaseManager<T1,T2> {
​
    public boolean add(T1 t1,T2 t2);
    public boolean del(T1 t);
    public boolean update(T1 t);
    public T1 findOne(T1 t);
    public List<T1> findAll();
}
​

或者在方法中单独设定:

public <E> boolean add(T obj,E e);

JDK8流式处理集合

JDK8引进了新的用于对集合处理的解决方案-流式处理,可以通过链式编程,函数式接口,lambda表达式简单便捷的对集合完成,过滤,排序,截取等操作。

public class StreamDemo {
​
    /**
     * 集合流式处理机制
     * @param args
     */
    public static void main(String[] args) {
        
        List<User> list = new ArrayList<>();
        list.add(new User("jackson", 22));
        list.add(new User("jack", 32));
        list.add(new User("aoteman", 40));
        list.add(new User("tom", 43));
        list.add(new User("atom", 22));
        list.add(new User("bob", 23));
        list.add(new User("jackson", 12));
        list.add(new User("rose", 62));
        list.add(new User("rose", 62));
        list.add(new User("kobe", 17));
        list.add(new User("curry", 16));
        
        list = list.stream()
                .filter(user -> user.getAge() > 18) //过滤掉所有年龄小于等于18的用户
                .sorted((u1,u2) -> u1.getAge() - u2.getAge())  //排序
                .distinct()             //去除重复(以hashcode为准:重写equals和hashcode)
                .skip(3)                            //跳过指定行
                .limit(5)                           //显示指定行
                .collect(Collectors.toList());      //收集数据
        
        //统计
        long count = list.stream().count();
        System.out.println("符号条件的数据行数:"+count);
        
        //forEach遍历
        list.stream().forEach(u->System.out.println(u));
        
        //获取所有用户的用户名,并拼接为字符串输出 jack,aoteman,tom,rose
        String s = list.stream().map(User::getName).collect(Collectors.joining(","));
        System.out.println(s);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37693860/article/details/81430596