Java基础01

string

  1. 构造方法每创建一次对象,都会在堆内存中开辟不同的对象空间。所以,每new一次,都是不同的对象。
  2. 直接定义的字符串内容会存储到堆内存中的常量池里。字符串内容如果相同,则直接共享使用。

字符串的比较

  1. ==号如果比较的是基本数据类型,比较的是具体的值,==号如果比较的是引用数据类型,比较的是对象的地址值
  2. 比较字符串内容是否相同,使用equals()方法

字符串的比较

  1. 记住俩个重要方法:length(),charAt(); 用for循环实现

StringBuilder

  1. 每拼接一个字符串,都会产生新的字符串对象。这种操作会比较浪费内存空间!StringBuilder来解决这个问题
  2. Stringbuilder是可变的字符串对象
public static String arryToString(int[] array){
2        StringBuilder stringBuilder = new StringBuilder();
3
4        stringBuilder.append("[");
5
6        for (int i = 0; i < array.length; i++) {
7            if(i==array.length-1){
8                stringBuilder.append(array[i]);
9            }else {
10                stringBuilder.append(array[i]).append(",");
11            }
12        }
13
14        stringBuilder.append("]");
15
16        String s = stringBuilder.toString();
17        return s;
18    }

String&StringBuffer&StringBuilder

  • String:不可变字符序列,底层使用char[]存储。
  • StringBuffer:可变的字符序列,线程安全的,效率低,底层使用char[]存储
  • StringBuilder:可变字符串序列,线程不安全的,效率高,底层使用char[]存储。

Collection

  • JDK不提供此接口的任何直接实现:它提供了更具体的子接口的实现,如Set和List 。
  • 用多态的方式创建collection对象。(具体实现类ArrayList)
  • collection用迭代器遍历,迭代器是一个内部类。
  • 迭代器创建的时候指向的不是第一个元素,而是第一个元素的上方空元素。判断是否有下一个元素是相对于当前迭代器指向的地方而言的。
  • 集合存储的是引用数据类型。不能存储基本数据类型。

List

  • 有序:存储和取出的是顺序一致。
  • 可重复:存储的元素可以重复。
  • 并发修改异常 ConcurrentModificationException
 1//并发修改异常 ConcurrentModificationException
2        List<String> list = new ArrayList<String>();
3        list.add("hello");
4        list.add("word");
5
6        Iterator<String> iterator = list.iterator();
7
8        while (iterator.hasNext()){
9            String s = iterator.next();
10            if(s.equals("word")){
11                list.add("JavaSE");
12            }
13        }
14
15        System.out.println(list);
16    }
17
18
19Exception in thread "main" java.util.ConcurrentModificationException
20    at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
21    at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)
22    at com.Gao.ArrayList.List_Demo.main(List_Demo.java:22)
  • 分析:源码分析之后可以看到迭代器遍历过程中,丢改了集合的长度,导致实际修改次数和预期修改次数不一致,从而抛出了异常
  • 解决方案: 在if之后家break跳出循环,防止执行checkForComodification();或者用for循环的方式。
  • 数组是查询快,增删慢的数据结构,链表是查询慢,增删快的数据结构。

list的常用子类ArrayList&linkedList

  • ArrayList底层是数组
  • linkedList底层是链表
  • 3种遍历方式 1.迭代器 2.for循环遍历 3. for增强遍历
linkedList集合特有功能
  • 因为是linkedList特有功能,所以不能用多态的当时创建(父类不能调用子类的方法)
  1. addFirst()
  2. getFirst()
  3. removeFirst()

set集合

HashSet

  • 不包含重复元素
  • HashSet该类实现Set接口,由哈希表(实际为HashMap实例)支持。 对集合的迭代顺序不作任何保证; 特别是,它不能保证订单在一段时间内保持不变。 这个类允许null元素。
  • 底层数据结构是哈希表

哈希值

  • JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
  • Object类中HashCode()方法可以获取对象的哈希值。
  • 同一个对象的哈希值是一样的。
  • 默认情况下不同对象的哈希值是不同的。(重写hashCode方法可以实现让不同字符串的哈希值相同)
保证元素唯一性的源码分析
 1public boolean add(E e) {
2                return map.put(e, PRESENT)==null;
3            }
4
5             static final int hash(Object key) {
6                    int h;
7                    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
8                }
9
10             public V put(K key, V value) {
11                    return putVal(hash(key), key, value, false, true);
12                }
13                // hash值和元素的hashCode()相关
14                final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
15                                   boolean evict) {
16                        Node<K,V>[] tab; Node<K,V> p; int n, i;
17                        //如果哈希表未初始化,就对其进行初始化
18                        if ((tab = table) == null || (n = tab.length) == 0)
19                            n = (tab = resize()).length;
20
21                            //根据对象的哈希值计算对象的存储位置,如果该位置没有元素就存储元素
22                        if ((p = tab[i = (n - 1) & hash]) == null)
23                            tab[i] = newNode(hash, key, value, null);
24                        else {
25                            Node<K,V> e; K k;
26                            /*
27                            存入的元素和以前的元素比较哈希值
28                            如果哈希值不同,会继续向下执行,把元素添加进去,
29                            如果哈希值相同,会调用equals方法
30                              返回true,元素重复不存储
31                              返回false 则存储
32
33                            */
34
35                            if (p.hash == hash &&
36                                ((k = p.key) == key || (key != null && key.equals(k))))
37                                e = p;
38                            else if (p instanceof TreeNode)
39                                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
40                            else {
41                                for (int binCount = 0; ; ++binCount) {
42                                    if ((e = p.next) == null) {
43                                        p.next = newNode(hash, key, value, null);
44                                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
45                                            treeifyBin(tab, hash);
46                                        break;
47                                    }
48                                    if (e.hash == hash &&
49                                        ((k = e.key) == key || (key != null && key.equals(k))))
50                                        break;
51                                    p = e;
52                                }
53                            }
54                            if (e != null) { // existing mapping for key
55                                V oldValue = e.value;
56                                if (!onlyIfAbsent || oldValue == null)
57                                    e.value = value;
58                                afterNodeAccess(e);
59                                return oldValue;
60                            }
61                        }
62                        ++modCount;
63                        if (++size > threshold)
64                            resize();
65                        afterNodeInsertion(evict);
66                        return null;
67                    }
哈希表保证元素唯一性实现方法
  1. 计算出带存入对象的哈希值
  2. 将哈希值对象对16求余。
  3. 分别存入0-15的地址
  4. 若地址一样,比较哈希值和内容,如果都不一样,则用链表插入该元素的后面。

LinkedHashSet

  1. 底层实现是哈希表和链表
  2. 由链表保证元素顺序,存入和取出的顺序一致。
  3. 由哈希表保证元素的唯一

TreeSet

  1. 元素有序(不是存取顺序),按照一定的规则进行排序,具体排序方法取决于构造方法。
  2. 没带索引,不能用普通for方法遍历,需要用增强的for方法。
  3. 由于是set集合所以元素没有重复的
  4. 用treeset存储自定义对象时,该对象的类要实现Comparable<>(自然排序)接口。
@Override
2    public int compareTo(Student o) {
3        int num = this.age-o.age;
4        num = (num == 0) ? this.name.compareTo(o.name) : num;
5        return (num);
6    }
  1. 比较器comparator的使用
1 TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
2            @Override
3            public int compare(Student o1, Student o2) {
4                int num = o1.getAge()-o2.getAge();
5                num = (num==0)?o1.getName().compareTo(o2.getName()):num;
6                return num;
7            }
8        });
  1. 比较器排序就是让集合构造方法接受比较器的实现类对象,重写compare方法。
  2. 不重复的随机数
1  Random random = new Random();
2        TreeSet<Integer> set = new TreeSet<Integer>();
3        while (set.size()<10){
4            set.add(random.nextInt(20)+1);
5        }
6
7        for (Integer integer : set) {
8            System.out.println(integer);
9        }

泛型

  1. 提供了编译时类型安全检测机制,本质时将类型参数化。
  2. 优点:将运行时期的异常提前到了编译期间,避免了强制类型转换
  3. 指定一种类型的格式,这个类型可以看成时形参
  4. 将来具体调用的时候给定的类型可以看成时实参,并且实参的类型只能是引用类型。

泛型方法

public <T> void show(T t){
2        System.out.println(t);
3    }

类型通配符

为了表示各种泛型List的父类,可以使用类型通配符

  • 类型通配符:
    List: 表示元素类型未知的List,它的元素可以匹配任何的类型
  • 这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
    如果说我们不希望List是任何泛型ist的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
  • 类型通配符 上限:
    List:它表示的类型是Number或者其子类型
    除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限
  • 类型通配符下限:
    List:它表示的类型是Number或者其父类型

Map集合

  1. 将键映射到值的对象。 Map不能包含重复的键; 每个键可以映射到最多一个值。
  2. HashMap<>(),的key和value的类型,不能是基本数据类型,需要时引用类型,所以要是基本类型的包装类,int-->Integer,char---->Character等等。

俩种遍历方式

 1//遍历map方式1
2        Set<String> keySet = map.keySet();
3        for (String s : keySet) {
4            System.out.println(s+":"+map.get(s));
5        }
6
7        //遍历map方式2
8        Set<Map.Entry<String, String>> entrySet = map.entrySet();
9        for (Map.Entry<String, String> mapEntry : entrySet) {
10            //mapEntry是每一个map对象
11            System.out.println(mapEntry.getKey()+"-->"+mapEntry.getValue());
12        }
posted @ 2021-04-19 08:28  17_Xtreme  阅读(41)  评论(0编辑  收藏  举报