java基础List,Set,Map集合部分(学习笔记)

集合操作(java.util*)

java.util.Collection

--------------->java.util.List

----------->java.util.ArrayList

------------>java.util.LinkedList

------------->java.util.Set

1.java.util.ArrayList

1.1 基本使用

底层操作就是一个数组(添加,移除,扩容)

基本使用 add ,size有效元素

添加元素

   ArrayList list = new ArrayList();//不写泛型默认object 容纳任何对象。
        Product p1 = new Product("001", "java課程1", 3000);
​
list.add(p1);

查看有效元素的个数

System.out.println(list.size());

获取某个元素,根据数组下标获取

取第0个元素

System.out.println(list.get(0));

直接打印他的对象相当于打印他的ToString 直接遍历打印每个对象的tostring

System.out.println(list);

添加元素,放在第三个位置可以在但是下标不能大于数组的大小 ,不然就下标越界相当于在数组下标范围内,任意位置插入一个元素。

list.add(3,p1);

如果你是一个聚集,那么就会提供一个遍历和访问元素的方式。这个就和设计模式相关,称为迭代器模式。

删除第3个位置的元素

list.remove(3);

集合的遍历

//遍历方式1
for (int i = 0; i <list.size(); i++) {
    System.out.println(list.get(i));
​
}

方式二

/**遍历方式2迭代器遍历
 *如果你是一个聚集,那么就会提供一个遍历和访问元素的方式。
 * 并且不暴露集合的实现
 * 这个就和设计模式相关,称为迭代器模式。
 * ArrayList类已经提供了迭代器
 * java.util.Iterator
 */
Iterator itor = list.iterator();
while (itor.hasNext()){
    Product pro = (Product) itor.next();
    System.out.println(pro);
}

方式三

会把第一个给obj,再把第2个给obj,再把3个给obj一直到最后一个

// 遍历方式三
//foreach 遍历
​
for(Object obj :list){
    System.out.println(obj);
}

//判断某个元素是否包含在集合中用contains 方法
//判断某个元素是否包含在集合中
​
System.out.println(list.contains(p1));

contains 方法注意和实际场景的使用

可以进行重写hashCode 然后选择那些属性是相同的就是一个对象。

list集合中可以放重复的元素。

ArrayList 源代码

两个重要成员 Object[] EMPTY_ELEMENTDATA = {};

int size;

一个是空数组,一个是存数组长度。

其实数组的初始大小是10;

扩容,后移的操作。

移除元素的时候要做前移操作。

注意:ArrayList 这种有数组最为底层的操作,最好估算元素的多少来指定底层数组的大小。

ArrayList list = new ArrayList(给定大小);

避免数组扩容操作,因为扩容操作会产生垃圾,占用内存,性能较差。

1,2 java.util.Vector

操作都是类似的

        Vector<String> vector = new Vector<>();
        vector.add("hello");
        vector.add("world");
        System.out.println(vector.size());
        System.out.println(vector);

默认大小也是10;

底层源代码 加了很多synchronized 关键字 ,区别就是一个线程安全一个线程不安全,

遍历方式都是一样,只不过是多了一种

 for (int i = 0; i <vector.size() ; i++) {
     System.out.println(vector.get(i));
 }
for (String str:vector){
    System.out.println(str);
}
 Iterator<String> itor =vector.iterator();
while (itor.hasNext()){
    String s = itor.next();
    System.out.println(s);
}
           //还有一种遍历方式
        Enumeration <String> e=vector.elements();
       while (e.hasMoreElements()){
           System.out.println(e.nextElement());
       }
​

底层也是数组的操作,大部分功能和ArrayList 类似。 有一种老的遍历方式 类似于 迭代器遍历。

ArrayList 线程不安全

Vector 线程安全

jdk7之前的版本扩容的大小稍有差异。

判断一个集合是否为空 isEmpty()

boolean b = vector.isEmpty();

2,LinkedList (链表结构)

2,1 基本使用和ArrayList 类似

LinkedList<String> list = new LinkedList<>();
list.add("mengzi1");
list.add("mengzi2");
list.add("mengzi3");
list.add("mengzi4");
// 有效元素的个数
System.out.println(list.size());
//移除一个元素
list.remove(2);
//打印对象里的所有内容
System.out.println(list);
//遍历
for (int i = 0; i <list.size() ; i++) {
    System.out.println(list.get(i));
}
for (String str :list){
    System.out.println(str);
}
Iterator<String> itor = list.iterator();
while (itor.hasNext()){
    String next = itor.next();
    System.out.println(next);
}

LinkedList 是一个链表结构 提供了一个非常方便的 头尾操作。

不需要元素的移位。直接指向就可以了。

addFirst,addLast,getFirst,getLast

适合做一个 头尾操作比较频繁的事,比如 :贪吃蛇

3,java.util.HashSet 集合

set 集合不能放重复对象,是否重复由equals 方法决定

注意:容纳的对象必须根据自己的唯一标识来重写equals 和hashCode方法。

注意:对象一旦放入HashSet 容器中,对象的标识属性值不能再修改,否则倒置对象移除不了。

HashSet 存放元素的时候元素的位置是和对象hashCode算法得到相关的。

那么去查找元素时,也要根据这个算法的值,然后去找到相关的位置,移除元素,如果

没有元素存在该算法的属性值在存放容器后被修改了,意味着hashCode算法得到和之前的值不一样了,就删除不了,久而久之就会存在内存泄露。

3.2 HashSet 的数据结构

HashSet底层就是HashMap

基本使用添加,移除元素,遍历,和之前的一样。

4.java.util.TreeSet

注意:TreeSet中容纳的对象,必须能够排序(排序的方式自己定义)

java中有两种排序的比较器

4.1 java.lang.Comparable

构造函数如果无参数,那么TreeSet 使用无参的构造函数,那么容纳的对象必须实现 Comparable 接口

package corelesson3;

import java.util.TreeSet;

public class TreeSetDemo1 {


    public static void main(String[] args) {

        User user1= new User("menzi1","123123",18);
        User user2= new User("lisi","12",21);
        User user3= new User("lisi","12",20);

        TreeSet<User> ts = new TreeSet<User>();
        ts.add(user1);
        ts.add(user2);
        ts.add(user3);
        System.out.println(ts);

    }
}

package corelesson3;

public class User implements Comparable<User> {
private String name;
private String pass;
private int age;

    public User() {
    }

    public User(String name, String pass, int age) {
        this.name = name;
        this.pass = pass;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public String getPass() {
        return pass;
    }

    public void setPass(String pass) {
        this.pass = pass;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

    @Override
    public int compareTo(User o) {
        if(!this.name.equals(o.name))
            //根据年龄字母来排序
        {
            return  this.name.compareTo(o.name);
        }else
            //如果名字相同 根据年龄来排序
        {
            return  this.age-o.age;
        }
        //这里内部会自己比较,然后做交换,我们只需要定义谁比较谁就可以了
}
}

4.2 java.util.Comparator

TreeSet 构造的时候使用Comparator 作为 构造函数的参数。

Comparator 是一个接口

package corelesson3;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo2 {
    public static void main(String[] args) {
        User2 user1 = new User2("mengzi1","24234",23);
        User2 user2 = new User2("mengzi2","24234",23);
        User2 user3 = new User2("mengzi3","24234",23);
        TreeSet<User2> ts = new TreeSet<User2>(new MyComparator());
        ts.add(user1);
        ts.add(user2);
        ts.add(user3);
        System.out.println(ts);
//  使用匿名类的方式实现接口Comparator
        TreeSet<User2> ts1 = new TreeSet<User2>(new Comparator<User2>() {
            @Override
            public int compare(User2 o1, User2 o2) {
                return o2.getName().compareTo(o1.getName());
            }
        });
        System.out.println("====================");
        ts1.add(user1);
        ts1.add(user2);
        ts1.add(user3);
        System.out.println(ts1);
    }
    //内部类方式实现接口Comparator
    private static class  MyComparator implements Comparator<User2>{
        @Override
        public int compare(User2 o1, User2 o2) {
            return o1.getName().compareTo(o2.getName());
        }
    }
}

两个对象 Comparator 比较 返回0 说明是同一个对象 是加不进容器里的

加入第一个,第二个是加不进去的。 添加,删除,遍历 ,和之前是一样的

4.3 数据接结构 底层是TreeMap

5,java.util.Map

  1. java.util.HashMap(key/vaule)

5.1 基本操作

package corelesson3;

import javax.activation.MailcapCommandMap;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HashMapDemo1 {
    public static void main(String[] args) {
        User3 u1 = new User3("001", "mengzi1", 20, "123456");
        User3 u2 = new User3("002", "mengzi2", 20, "123456");
        User3 u3 = new User3("003", "mengzi3", 20, "123456");
        User3 u4 = new User3("004", "mengzi4", 20, "123456");
        HashMap<String ,User3>  map = new HashMap<>();
        map.put(u1.getId(),u1);
        map.put(u2.getId(),u2);
        map.put(u3.getId(),u3);
        map.put(u4.getId(),u4);
        //获取map 容器的大小
        System.out.println(map.size());
        //直接打印它的tostring ,打印全部内容
        System.out.println(map);
        //获取某个元素 获得001 的信息
        System.out.println(map.get("001"));

        System.out.println("==================================");
        //判断某个key 是否存在
        System.out.println(map.containsKey("002"));
        // 是否包含某个value
        System.out.println(map.containsValue(u2));
        // 删除某个元素
        User3 rm = map.remove("002");


        /**
         *  遍历方式1: 把Map中所有的key 都放入set 集合中,然后遍历set 集合
         *    然后遍历Set集合, 得到key,通过key 获取value
         */
        System.out.println("==========================================");
        Set<String> set =map.keySet();
        for ( String key:set){
            User3 u = map.get(key);
            System.out.println(key +"="+u);

        }
        System.out.println("=============================");
        /**
         *   遍历方式2
         *   放入HashMap集合中的key,value 其实都会被包装成
         *   Map.Entry这个内部类的属性,
         *   有一个键值对就存在一个Map.Entry的实例对象
         *   通过entrySet()方法就可以吧这些实例对象都放入Set集合
         *   遍历Set 获取每一个对象。
         *每一个类型都有getKey 和getValue
         */
        Set<Map.Entry<String,User3>> set1=map.entrySet();
    for(Map.Entry<String,User3> me:set1){
        System.out.println(me.getKey()+"="+me.getValue());
    }
    }
}

注意: map.put(key,value) 如果key 相同的话 会覆盖前面的value值。

这个特点特别适合用来做计数,

map统计次数

package corelesson3;

import java.util.HashMap;

public class HashMapDemo3 {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("x",10);
        map.put("y",20);
        //后面x 的值 会覆盖前面的值
        map.put("x",30);
        //这个特点适合用来做计数
        System.out.println("====================================");
      String s="asfdasdfsdyasdiobnvuyxzmsdfkshnmoivzvxbbnlajshkjtyierghacb";
        /**
         *  计算每个字符出现的次数;
         *  思路:拿到每个字符,作为key 放入HashMap中,
         *  如果map 不中存在,那么put(key,1);
         *  如果已经存在 那么put(key,value+1);
          */
        HashMap<String, Integer> map1 = new HashMap<>();
        //1 遍历
        for (int i = 0; i <s.length() ; i++) {
            String key=s.substring(i,i+1);
            if(!map1.containsKey(key)){
                //不存在就放进去
                map1.put(key,1);
            }else
            {
                //已经存在就加1
                map1.put(key,map1.get(key)+1);
            }

        }
        System.out.println(map1);
    }
}

package corelesson3;

import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeSet;

public class HashMapDemo4 {
    public static void main(String[] args) {

        //要求计数,并且次数按照降序,如果次数相同 ,按照字母升序排序
        /**
         *  思路:  通过HashMap 集合就可以实现计数操作
         *  要排序 可以采用TreeSet 集合
         *  并且是根据放入TreeSet 中的对象的属性进行排序的;
         *  抽取出一个类来完成这件事
         */

      String s="asfdasdfsdyasdiobnvuyxzmsdfkshnmoivzvxbbnlajshkjtyierghacb";
        HashMap<String, Integer> map1 = new HashMap<>();
        //1 遍历
        for (int i = 0; i <s.length() ; i++) {
            String key=s.substring(i,i+1);
            if(!map1.containsKey(key)){
                //不存在就放进去
                map1.put(key,1);
            }else
            {
                //已经存在就加1
                map1.put(key,map1.get(key)+1);
            }

        }
        //System.out.println(map1);
        /**
         * 遍历HashMap 集合,然后把每一个key/value 都包装成T对象的实例
         *  放入TreeSet 集合,就完成了排序
          */
        TreeSet<T> ts = new TreeSet<>();
        for(String key:map1.keySet()){
            T t = new T(key,map1.get(key));
            ts.add(t);
            System.out.println();
        }
        //然后遍历这个集合,或者直接打印
        System.out.println(ts);
        System.out.println("==================================");
        for (T str:ts) {
            System.out.println(str);
        }
        System.out.println("========================");
        //迭代器遍历
        Iterator<T> itor = ts.iterator();
        while (itor.hasNext()){
            System.out.println(itor.next());
        }

    }
}
class T implements Comparable<T>{
    private  String name;
    private  int count;
    public T() { }
    public T(String name, int count) {
        this.name = name;
        this.count = count;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    @Override
    public String toString() {
        return name +": "+count +"次";
    }

    //定义排序的规则
    @Override
    public int compareTo(T o) {
        if(this.count!=o.count){
           return o.count-this.count;
        }else {
            return this.name.compareTo(o.name);
        }
    }
}

5.2 HashMap 数据结构

底层是一个数组加链表的结构,默认大小是16, 当hash值相同的时候就会放在链表里面,当链表程度大于8 的时候会转化为红黑树,当链表大小小于8 的时候,红黑树会转化为链表。

key/value 放入HashMap 的时候会被包装成Entry 的对象。

b,HashMap 的成员就有Entry的数组,该数组的大小默认是16,永远是2 的次方数

put(key,value) 时 其实就是转化成Entry对象并放入数组中。

c.put方法的实现

1,根据key 做一个hash 算法运算 得到一个hash值。

2,得到hash值去确定 数组的位置。 把hash,和数组长度 传过去。

做的事情就是 hash & (length-1)

等价于 hash % table.length length 是2 的次方数。

正好,获取到了数组的位置 (比如:3 %16 就拿到第三个数组的位置)

3 如果这个位置没有元素,直接包装Entry的实例并给数组赋值,如果计算出的位置已经有元素存在,就要判断是否相同,如果相同,则覆盖,并且要遍历整个链表,如果不覆盖,插入到链表头部。

如果计算出来的位置相同,这就是冲突率,我们要减少冲突率,因为一旦放入链表中,以后总是要遍历链表,效率差,要尽量把元素直接放入数组。而非链表。

所以要根据实际情况 重写hashCode和equals方法

注意2; 底层是数组,尽量减少扩容,所以HashMap 放入元素 也应该估算数组大小,避免扩容操作。

HashMap 中有加载因子 默认:0.75 扩到大2*length

5.3, get 方法实现

通过key 查找元素的算法和放入是一样的。

所以一打放入HashMap就不应该修改和hashCode和equals 方法生成相关属性的值。否则就会找不到。

6 , TreeMap (key/value)

key 必须要能够根据某种规则排序

通过两种比较器,TreeSe用底层就是TreeMap

添加 ,删除,遍历的方式

package corelesson3;
import java.util.Comparator;
import java.util.TreeMap;
public class TreeMapDemo1 {
    public static void main(String[] args) {
        TreeMap<User, Integer> users = new TreeMap<>();
        User user1= new User("menzi1","123123",18);
        User user2= new User("lisi","12",21);
        User user3= new User("lisi1","12",20);
        users.put(user1,1);
        users.put(user2,2);
        users.put(user3,3);
      // 遍历方式 两种 和hashmap  是一样的

        for(User key:users.keySet()){
            System.out.println(key+"="+users.get(key));
        }
        System.out.println("=============================");
        //定义名字排序规则
        TreeMap<User, Integer> users1= new TreeMap<>(new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return o2.getName().compareTo(o1.getName());
            }
        });
        users1.put(user1,1);
        users1.put(user2,2);
        users1.put(user3,3);
        System.out.println(users1);
    }
}

7.HashTable

和HashMap 相比,类的层次结构不一样。当然都实现了Map接口。基本操作都是类似。

package corelesson3;

import java.util.HashMap;
import java.util.Hashtable;

public class HashTableDemo1 {
    public static void main(String[] args) {
        Hashtable<String, String> hs = new Hashtable<>();
        // 添加元素
        hs.put("aa","123");
        hs.put("bb","456");
        hs.put("cc","321");
        hs.put("dd","876");
        //移除元素
        hs.remove("aa");
        hs.remove("dd","876");
     // 打印对象tostring
        System.out.println(hs);
        //遍历
        for(String key:hs.keySet()){
            System.out.println(key+"="+hs.get(key));
        }

        HashMap<Object, Object> hm = new HashMap<>();
        hm.put(null, null);
        System.out.println(hm);
       // hs.put(null,null);  //会抛出 NullPointerException
    }
}

7.2 hashMap 可以放 null的值

hashTable 不可以放 null 的值 会抛出NullPointerException 的异常

hashTable 底层源码有很多synchonized 的关键字。

7.3 Hashtable 是线程安全的

线程并发时效率低,但是能保证数据一致性

HashMap 是线程不安全的(线程并发时效率高,数据可能不一致,存在安全问题)

7.4 HashTable还有一个子类 Properties

java.util.Properties 类这个类在将来用的比较多,用来加载资源文件。

  1. java.util.Collections 类

    该类封装了一些对集合的操作都是静态方法。

    面试有时会问和Collection类有什么关系,其实两个没有任何关系。

Collections 类封装了集合常用的静态方法

Collection 是集合类的上层接口,是 Set接口和List接口的父接口

package corelesson3;
​
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
​
public class CollectionsDemo1 {
​
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("ee");
        list.add("cc");
        list.add("dd");
        //集合打印
        System.out.println(list);
        //把里面的数组做倒置
        Collections.reverse(list);
        System.out.println(list);
        System.out.println("=============================");
        // 给属数组做一个排序
        Collections.sort(list);
        System.out.println(list);
        System.out.println("=============================");
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //做一个倒叙排序,改变比较的o1 和o2 位置即可
                return o2.compareTo(o1);
            }
        });
        System.out.println(list);
        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(10);
        list2.add(20);
        list2.add(1000);
        list2.add(30);
     // 直接获取最大值
        System.out.println(Collections.max(list2));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java是一种广泛使用的编程语言,有简单、面向对象、跨平台等特点。下面是Java学习的一些重要知识点和学习笔记: 1. Java基础: - 数据类型:Java提供了多种数据类型,包括基本数据类型和引用数据类型。 - 控制流程:学习如何使用条件语句(if-else、switch)、循环语句(for、while)等控制程序的流程。 - 数组:了解如何声明、初始化和操作数组。 - 方法:学习如何定义和调用方法,以及方法的参数和返回值。 - 类和对象:理解类和对象的概念,学习如何定义类、创建对象和使用类的成员变量和方法。 - 继承和多态:掌握继承和多态的概念,了解如何使用继承创建子类,并实现方法的重写和多态的应用。 2. 面向对象编程: - 封装:学习如何使用访问修饰符(public、private、protected)来控制类的成员的访问权限。 - 继承:了解继承的概念和作用,学习如何使用extends关键字创建子类。 - 多态:理解多态的概念和实现方式,学习如何使用父类引用指向子类对象,实现方法的动态绑定。 3. 异常处理: - 异常的分类:了解异常的分类(Checked Exception和Unchecked Exception)和常见的异常类型。 - 异常处理机制:学习如何使用try-catch语句捕获和处理异常,以及使用throws关键字声明方法可能抛出的异常。 4. 输入输出: - 文件操作:学习如何读写文件,包括使用File类、字节流和字符流等。 - 序列化:了解对象的序列化和反序列化,学习如何将对象保存到文件或网络中。 5. 集合框架: - 学习Java提供的集合框架,包括ListSetMap等常用的集合类,以及它们的特点和用法。 6. 多线程编程: - 学习如何创建和管理线程,了解线程同步和线程间通信的方法。 7. 数据库连接: - 学习如何使用Java连接数据库,执行SQL语句,进行数据的增删改查操作。 以上是Java学习的一些重要知识点和学习笔记,希望对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值