记录《疯狂Java讲义精粹》划线内容及理解(第6章-java集合概述)

2023-11-05 05:30

本文主要是介绍记录《疯狂Java讲义精粹》划线内容及理解(第6章-java集合概述),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第六章 java集合概述

6.1 Java集合概述

java集合,是为了解决数组的两个问题而产生


1-存储的元素个数是定长的,所以list存储的元素个数是变长的

2-数组无法存储具有一定映射关系的数据,所以map由键值对构成

        集合中只能存放对象,

        数组中可以存放对象和基本类型的数据

java集合的根接口有两个


                1.collection接口,派生出

                                set无序集合(集合)
                                queue队列
                                list有序集合(列表)


                2.map接口,派生出
                                hashmap(键值对), 等各种形式的map,

值得注意是hashmap是线程不安全的,因为它允许valus为null


如果把队列queue看成一种特殊的list,那么集合的根接口一共扩展出来三类集合(也称容器),


set罐子,丢入的数据不可重复,且无序,访问时根据元素本身访问


list罐子,数据可重复,系统能记住元素顺序,访问需通过元素下标访问

map罐子,value可重复,key不能重复,无序,访问通过key来访问


为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组),Java提供了集合类。


Java的集合类主要由两个接口派生而出:Collection和Map


我们可以把Java的所有集合分成三大类,其中

Set集合类似于一个罐子,把一个对象添加到Set集合时,Set集合无法记住添加这个元素的顺序,所以Set里的元素不能重复(否则系统无法准确识别这个元素);

List集合非常像一个数组,它可以记住每次添加元素的顺序,只是List的长度可变。

Map集合也像一个罐子,只是它里面的每项数据都由两个值组成

6.2 Collection和Iterator接口

collection接口提供的操作集合的方法,适用于set.list.queue添加元素add


把集合中所有元素添加到另一集合中addall

清除所有元素clear


判断是否包含某个集合containsall

判断集合为空isempty


返回该集合的迭代器,用于遍历该集合iterator

值得注意该方法返回的是一个iterator对象


删除指定元素remove


与指定集合做差集removeall

做交集retainall


返回集合元素个数size


将该数组转化为数组toarray
 


在普通情况下,当我们把一个对象“丢进”集合中后,集合会忘记这个对象的类型——也就是说,系统把所有的集合元素都当成Object类的实例进行处理。从JDK 1.5以后,这种状态得到了改进:可以使用泛型来限制集合里元素的类型,并让集合记住所有集合元素的类型。

6.2.1 使用Iterator接口遍历集合元素

关于iterator该接口的对象必须依附于collection集合而存在,该接口提供了三个方法用于迭代遍历集合


1-判断元素是否被遍历hasnext

2-获取一个元素next


3-删除上次用next获取到的元素remove


在iteraton遍历过程中,不可改变集合元素,否则发生异常,但可以通过非常危险的操作在iterator中改变元素,原理具体细节未知

在iterator执行过程中,传入的是集合元素的值,而不是地址,这意味着无法通过iterator来改变集合元素

6.2.2 使用foreach循环遍历集合元素

foreach于iterator具有相同的两点性质,遍历过程中不可改变,接收的是元素值,

foreach语句更加便捷,只需要for(类型变量名:需要遍历的集合名)就可遍历

6.3 Set集合

set集合不接受相同的元素,set判断的标准是equals方法返回true

6.3.1 HashSet类

set的三大子类之一,hashset,采用hash算法存储元素,所以具有良好的效率,主要使用对象的hashcode方法计算hash值,关于hashset有些特点,


1-不保证元素排列顺序,


2-多线程访问hashset不同步,

3-允许值为null


hashset主要通过equals和hashcode方法来判断元素是否可以加入集合,equals用来判断元素是否相等,hashcode用来计算元素的值(存储位置)


有三种特殊情况,


1-equals和hashcode都返回true可以加入集合


2-equals返回true hashcode返回false,可以加入,将两个相同的元素存在set的不同位置


3-equals返回false hashcode返回true,可以加入,将在set的同一位置用链式存储多个对象,但这样查找是将使效率下降,而hashset最重要的价值就是hash算法的效率


重写hashcode方法的一般规则,


1-把每个要用equals比较的field计算出一个int类型的hashcode值(这个值得计算比较复杂,详情可参见表)


2-把计算出来的每个hashcode乘一个质数再相加,作为hashcode方法的返回值

-------------------------------------------


 


HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。

6.3.2 LinkedHashSet类

linkedhashset同样使用hashcode方法来确定元素的存储位置,但他使用链表来维护元素插入顺序,所以在插入时他的性能低于hashset,但是在遍历输出是有更好的性能(因为他的元素是有序的,输出也是按照添加时的顺序输出的)

6.3.3 TreeSet类

treeset与linkedhashset差不多,都能保证元素的有序性


但linkedhashset维护的是插入时的顺序,treeset维护的是按照对象值排列的顺序,treeset采用红黑树来存储(考研考点),


有两种排序方式,默认为自然排序,升序排列,或者实现comparator方法自定义排序


它提供了一些方法,
1-comparator定制排序,如未定制则返回null

2-first,返回第一个元素


3-last,返回最后一个元素


4-lower,返回比指定值小的元素,

5-higher,返回比指定值大的元素,

6-subset,返回指定区间的子集(包头不包尾)


7-headset,返回小于给定值得子集,

8-tailset,返回大于等于给定值得子集


看起来很乱,其实很好记,返回值是,第一个,最后一个,前一个,后一个,三个子集,(前一个后一个中给定的值不需要存在于集合中)


默认排序时,使用的是comparable类的compareto,比较a.b两数,a大于b返回1,否则为-1,相等为0,且向treeset中添加一个对象时,该对象的类必须实现comparable类的compareto方法


有两个特殊点,
1-如果没有实现这个类,则只能向treeset插入一个值,且不能取出,否则引发异常,
2-如果向treeset添加的不是一个类的对象,也会引发异常,原因在于compareto方法要求两个比较的对象是同一类


你可以通过自定义comparable类的方法,使多个不同类加入到treeset中,但取不出来,(重写compareto方法,不强制转换类型)


为了使treeset正常使用,应该保证treeset中的对象,使用equals和compareto方法的比较结果一样,可以通过重写方法达到这一目的


在treeset中放去可变对象,将面临和hashset同样的问题,只要放入后改变值,treeset将找不到改变值得元素,顺序也会变得混乱,这是因为treeset会在加入时检查并排序,但在改变集合中元素值时不会管他,这种情况下可以删掉一个没有改值得元素,那么集合会重新索引(不是重新排序),就能删所有元素了


在自定义排序时要提供一个compartor对象与treeset关联,且要实现他的compare方法作为比较标准,这个compartor对象要作为treeset的构造器参数传入


如果试图把一个对象添加到TreeSet时,则该对象的类必须实现Comparable接口

6.3.4 EnumSet类

EnumSet在内部以位向量的形式存储,这种存储形式非常紧凑、高效,

因此EnumSet对象占用内存很小,而且运行效率很好,

enumset不允许插入null,否则会报空指针,如果想测试或者删除其中的null值,会返回false

enumset没有提供构造方法,但是提供了一些静态方法用于创建对象,

1-allof用指定枚举类的所有变量创建一个集合


2-complementof,假设有一个四个枚举值得枚举类,有一个enumset使用了该类的三个值创建了集合,则将该enumset作为参数传入该方法,创建的enumset中报告剩下的那一个枚举值


3-copyof,使用普通集合创建enumset,但这个普通集合中的值要属于同一枚举类


4-copyof,传入一个enumset,将复制一个该集合


5-noneof,传入一个枚举类,创建一个元素类型为该类的空集合


6-of 创建一个由一个或多个枚举值组成的集合,这些枚举值必须是同一类的


7-range,创建一个包含枚举值1到2之间所有枚举值得集合,这个顺序关系在于他们在类中的顺序
 


EnumSet在内部以位向量的形式存储,这种存储形式非常紧凑、高效,因此EnumSet对象占用内存很小,而且运行效率很好

6.3.5 各Set实现类的性能分析

enumset性能最好,hashset其次(尤其对添加查询等操作有良好的性能),tteeset再其次,


如果需要维持set中的元素的排序关系,用treeset,

如果想快速遍历,用linkedhashset,


值得注意的是,collection下的enumset, hashset,treeset都是线程不安全的,

 也就是说当多个线程同时访问一个set时,这个集合中的元素将不同步,

通常使用collections工具类的synchronizedSortedSet方法来包装set,解决上述问题

6.4 List集合

list与set的不同,

1)元素有序,list按添加顺序为元素添加索引

2)元素可重复

6.4.1 List接口和ListIterator接口

list的常用方法

1)add 添加元素(到指定位置参数顺序为,(位置,元素))

2)addAll(位置,子集)将指定集合中的所有元素添加到指定位置

3)get返回指定索引位置的元素

4)indesOf返回元素在list中,第一次出现的位置(索引值)

5)lastindexOf返回元素在list中,最后一次出现的索引值

6)remove删除指定位置的元素(还会返回该元素?)

7)set(位置,元素)将指定位置的元素替换

8)sublist(开始,结束)返回从开始位置到结束位置的,list子集

9)iterator返回一个listiterator对象,用于迭代liat

6.4.2 ArrayList和Vector实现类

这两个list的实现类都是基于数组实现,他两都封装了一个object的数组,使用initialcapacity参数来设置数组的长度(默认长度为10),且这个参数会自动增加(如果数组不够用了)

1)ensureCapacity(int q)将数组长度增加q,(其实改变的就是initialCapacity的值)

2)trimToSize()调整数组的长度为元素个数(缩减数组,减少空间占用)

vector是早期java 的一个list,之后java提供arraylist之后就很少用了,但vector是线程安全的,而arraylist不是,线程安全的好处付出的代价就是性能的下降

vector还有一个子类,Stack,可以用来模拟栈(LIFO)(太老了,不推荐,模拟栈可以用linkedlist)

注意栈和set一样,都会忘记进入数据的类型,而统一当作object,所以取出来的数据要类型转换

stack类的方法

1)peek()返回栈的第一个元素,该元素不会出栈

2)pop()将栈顶元素出栈

3)push(object m)将元素入栈(压入栈顶)

6.4.3 固定长度的List

操作数组的工具类arrays,有一个内部类,arraylist,他是一个固定长度的list,并且只能遍历,不能增加和删除

array类的aslist方法,可以将一个数组,或者指定个数的对象,转换为一个list,而创建的这个list,就是array的内部类arraylist的实例,

补充(2023.8.8)

使用上述方法生成的list不可改变,对该list的操作在编译期不会报错,但运行到之后会抛出  UnsupportedOperationException(不支持操作)异常。

6.5 Queue集合

queue也就是队列(FIFO,先进先出),接口中的方法有

add(元素)将指定元素加入队尾

offer(元素)将指定元素加入队尾

element()获取队头元素,不删除

peek()获取队头元素,不删除,如队列为空,返回null

remove()获取对头元素,并删除

poll()出队,为空返回null

queue是一个接口,他下面有

        1)priorityQueue实现类,

        2)Deque接口,这是一个双端队列,也可以当作栈来用,

java为Deque提供了ArrayDeque和linkedlist两个实现类

6.5.1 PriorityQueue实现类

这个不能说是队列,而更像是一个堆,

因为如果将元素加入队列,那么PriorityQueue会将其中的所有元素排序,如果出队时,将会弹出队列中最小的元素

priorityQueue不允许插入null

因为该实现类需要对加入的元素排序,所以priorityQueue提供了两种排序方式,

1)自然排序

如果使用这种方式,则加入该Queue的对象必须实现comparable接口,并且必须是同一个类的实例

2)定制排序

也是使用comparator作为传入对象,作为排序依据,这个前面有具体解释,不再赘述

6.5.2 Deque接口与ArrayDeque实现类

Deque接口,定义的方法

1)assFirst 将指定元素插入双端队列的开头

2)addlast 将指定元素插入双端队列的末尾

3)descendinglterator 返回对应集合的迭代器,该迭代器以逆向顺序遍历集合(队列)中的元素

4)getFirst 获取队头元素,不删除

5)getLast 获取队尾元素,不删除

6)offerFirst 将指定元素插入队头

7)offerLast 将指定元素插入队尾

8)peekFirst 获取队头元素,不删除,为空返回null

9)peekLast 获取队尾元素,不删除,为空返回null

10)pollFirst 获取对头元素,并删除,为空返回null

11)pollLast 获取队尾元素,并删除,为空返回null

12)pop 出栈

13)push 入栈

14)removeFirst 获取队头元素,并删除

15)removeLast 获取队尾元素,并删除

16)removeLastOccurrence 删除该队列最后一次出现的指定元素

Deque接口的实现类,ArrayDeque,基于数组实现的双端队列,可用numElements指定数组长度,默认为16

那么这个ArrayDeque就可以用作栈,因为包含pop和push方法

6.5.3 LinkedList实现类

linkedlist实现了两个接口,list和Deque,所以他是一个可以当作栈,或双端队列的list集合

我在测试时发现一个问题,如果用for和pop,来循环遍历list,总会出错,因为最后的几位不会被输出,

原因在于,我的for的终止条件为

for (int i = 0; i < s.size(); i++)

每次在for中pop出一个元素,size()的长度就会减一,而i++还在增长,双向奔赴会付出代价

linkeslist,使用链表实现,插入删除时性能很好

arraylist,arrayDeque,使用数组实现,随机访问时性能很好(Vector也是数组,但为线程安全付出了代价)

6.5.4 各种线性表的性能分析

先对以上的类做数据结构的分类,

线性表list 遍历时用get

​         1)基于数组的线性表 arraylist

​         2)基于链表的线性表 linkedlist

队列queue 遍历时用iterator 插入删除性能很好

​         1)双端队列/栈 Deque

6.6 Map

MAP是一种储存映射关系的数据结构,它包含两部分,key集和对应的value集,

key集类似一个set,元素不能重复,(其实map和set的关系很深,包括底层实现,方法)

value集类似一个list,元素可以重复,可以通过下标(对应的key)来访问对应的元素

在java底层实现map时,其实封装了一个Entry内部类,来存储key-value对,

并且,从java源码来看,它先是实现了map,然后包装了一个value都为null的map,就实现了set

map也被成为字典,或关联数组

map接口定义的常用方法

1)clear 清除该map所有的键值对

2)containsKey(key) 查询map中是否包含指定key,返回布尔值

3)containsValue(value) 查询map中是否包含一个或多个value值,返回布尔值

4)entrySet() 返回map中所有的key-value对,组成的set,key-value的表现形式是Map.Entry对象

5)get(key) 返回指定key所对应的value,如不存在返回null

6)isEmpty() 查询map是否为空,返回布尔值

7)keySet() 返回map中,所有key组成的set

8)put(key,value) 向map添加一个键值对,如键已存在,则会被覆盖

9)putAll(map) 将指定map的所有键值对复制到本map

10)remove(key) 删除key所对应的value,返回的是被删除的value,如key不存在返回null

11)size() 返回map中的键值对个数

12)values() 返回map中,所有value组成的collection(也就是集合)

map中的entry内部类封装了键值对,包含三个方法

        1)getKey() 返回该Entry里的key

        2)getValue() 返回该Entry里的value

        3)setValue(value) 设置该Entry的value,返回新的value值

6.6.1 HashMap和Hashtable实现类

HashMap和Hashtable,类似Arraylist和Vector的关系

Hashtable是一个古老的map类,和vector一样从jdk1开始就存在,同样,他是线程安全的,它不允许将null作为key和value

hashmap的键值可以用null来赋值,但由于key的值不能重复,所以只能有一个key为null的键值对

hashmap的tostring已经被重写了,它的返回格式总是         key1=value1

在map中如果要使用自定义类,作为key的元素对象,必须要重写hashcode()方法和equals()方法,

hashmap和hashtable,的key相等的判断标准

                1)两个key通过equals()方法返回true

                2)通过hashcode()方法也返回true

他们两的value判断标准

                1)两个value通过equals()方法返回true

和list,已经set一样,如果已经存入的元素是可变的,在存入之后改变它,对应的存储结构将不能再准确的访问到被修改的元素

在map中,尽量不要使用可变元素作为key

6.6.2 LinkedHashMap实现类

linkedhashmap可以维护key插入时的顺序,因为它使用了双链表,所以优点是插入删除的效率高,缺点是随机访问时效率底

关于遍历map,有两种方法

                1)使用keyset来获取map的所有键值对,再用eafor循环来遍历

                2)直接使用对应map的迭代器

6.6.3 使用Properties读写属性文件

properties是hashtable的子类,它可以处理属性文件,properties类可以将map对象和属性文件关联起来,比如读取,写入

properties类提供的方法

1)getProperty(key) 获取properties中,指定属性名对应的属性值

2)getProperty(key,defaultvalue) 也是获取指定key的value值,如指定key不存在,则指定默认值

3)load(inputstream instream) 从属性文件中加载键值对,追加到properties中

4)store(outputstream out,string comments)将properties中的键值对输出到指定的属性文件中

3和4方法中的形参都是输入输出流,

6.6.4 SortedMap接口和TreeMap实现类

Map的子接口sortedMap,sortedmap接口的实现类,就是TreeMap

TreeMap使用红黑树作为存储结构,树中的每个节点就是一个键值对,树的排序依据是key值

同样有两种排序方式

1)自然排序

TreeMap中,key必须是同一个类,并且这个类要实现comparable

2)定制排序

创建TreeMap时传入一个comparator对象,它负责对树中的元素排序

TreeMap中,元素相等的判断标准,两个key通过compareTo()方法返回0

如在TreeMap中,key为自定义类,那么需要保证compare To()方法和equlas()的返回结果一致

TreeMap中的方法(第一个,最后一个,前一个,后一个,截取子集)

firstEntry() 返回该map最小的key,所对应的键值对,为空返回null

firstKey() 返回该map中最小的key值,为空返回null

lastEntry() 返回该map中最大的key,所对应的键值对,为空返回null

lastKey() 返回该map中最大的key值,为空返回null

higherEntry(key) 返回该map中,位于指定key后一位的键值对

higherKey(key) 返回该map中,位于指定key后一位的key

lowerEntry(key) 返回该map中,位于指定key前一位的键值对

lowerKey(key) 返回该map中,位于指定key前一位的key

subMap(开始位置,是否包含开始,结束位置,是否包含结束) 返回该map 的一个子集

subMap(开始(包括),结束(不包括)) 返回一个该map 的子集

tailMap(值) 返回该map的一个子集,key值大于指定值

tailMap(值,是否包含值) 返回该map的一个子集,key值大于指定值

headMap(值) 返回map的一个子集,key值小于指定值

headMap(值,是否包含值) 返回map的一个子集,key值小于指定值

6.6.5 WeakHashMap实现类

WeakHashMap与HashMap类似,不同点在于,HashMap对key是强引用,但WeakHashMap只有对key实际对象的弱引用,

因此如果垃圾回收程序,回收了key所对应的实际对象之后,WeakHashMap将会自动删除该key所对应的键值对

6.6.6 IdentityHashMap实现类

IdentityHashMap与HashMap类似,但IdeatityHashMap对两个key的,相等判断更加严格,必须两个key用==相等时,它才认为两个key相等

6.6.7 EnumMap实现类

EnumMap是一个与枚举类一起使用的Map,在创建它时要指定它对应的枚举类,并且其中的key都要为枚举类中的枚举值

EnumMap的底层使用数组实现,并且它维护,基于枚举类内部,每个枚举值的顺序(称为自然顺序),来维护每个键值对的顺序

EnumKey的key不允许使用null

6.6.8 各Map实现类的性能分析

这一小节了解到的map有

        1)Hashmap,

        2)hashtable,

        3)treemap,

        4)linkedhashmap,

        5)IdentityHashMap,

        6)EnumMap,

        7)WeakHashMap

性能最好的时EnumMap

其次是HashMap,其次稍差一点的是Hahstable,因为它线程安全

treemap和linkedhashmap差不多,但treemap能保持元素有序,但在插入删除是比较慢,

linkedhashmap正好在插入删除时效率高

IdentityHashMap和WeakHashMap性能一般,只是两个比较特殊的实现类

6.7 HashSet和HashMap的性能选项

Hash能存储元素的位置,称为”桶“,如果一个”桶“存储两个元素,则在同一位置用链表,存储多个元素,

在hash表中包含如下属性,

容量,桶总数

初始容量,如表意

尺寸,当前表中已装载桶,的数量

负载因子,尺寸/容量,0表示空,1表示满

负载极限,当负载因子到达负载极限时,hash表将成倍的增加桶的容量,并重新分配桶内元素,成为rehashing

hashmap和hashset,以及hashtable,默认的负载极限是0.75,也可在调用构造器时指定负载极限

负载极限,

如果太高,表空间占用内存较少(不发生rehashing),但查询时长增加,

如果太低,增加内存开销,但查询时长缩短

推荐如果刚开始就知道hash表内的最高容量,则手动指定初始化容量

6.8 操作集合的工具类:Collections

6.8.1 排序操作

collections提供,list排序的方法(以下方法都是静态)

reverse(list)反转指定list中,元素的顺序、

shuffle(list)对指定list随机排序(洗牌,这个比喻真好)

sort(list,comparator)根据comparator的顺序,对指定list排序

swap(list,i,j)将指定list 的,下标i,j处的元素互换

rotate(list,i)

i>0,将list最后的i个元素整体移到前面

i<0,将list前面的i个元素整体移到后面

这里有一个好玩的梭哈游戏,等我补全单独记录

6.8.2 查找、替换操作(以下方法都是静态)

binarySearch(list,key)对指定list(该list要有序)使用二分搜索,获取key的索引,

max(collection) 根据元素自然顺序,返回最大元素 (这里的自然排序,对于int的整数,就是大小关系,也就是调用compareTo()方法)

max(collection,comperator) 根据comparator指定的顺序,返回集合的最大元素

min(collection)根据自然顺序,返回集合中的最小元素

min(collection,comparator) 根据comparator指定的顺序,返回集合中的最小元素

fill(list,object)使用指定元素object替换list中的所有元素

frequency(collection,object)返回元素object在collection中出现的次数

lastIndexOfSubList(来源,目标)返回子list在父list中,第一次出现的位置,如无子list,返回-1

replaceAll(list,oldval,newval)在指定list中,使用一个新值,替换list中的所有指定旧值

6.8.3 同步控制

Vector和Hashtable,这两个古早的list和map是线程安全之外,别的几乎都是不安全的,

将集合包装成线程安全,要用到一个方法

Collections的synchronizedXxx方法

xxx的地方可以填list,map,set,collection,将这个方法的返回值赋给指定的集合类型,就可获得线程安全的实现类

6.8.4 设置不可变集合

collections有如下三个方法,来返回不可变集合

emptyXxx() 返回一个空的,不可变的集合对象,(xxx可为,list,map,set)

singletonXxx() 返回一个只包含指定对象/元素的,不可变的集合对象

unmodifiableXxx () 返回指定集合对象的不可变视图(只读版本)

6.9 烦琐的接口:Enumeration

一个古早的迭代遍历工具,和hashtable,Vector,以及Bitset都是从JDK1.0时,就存在的

这个接口主要用来遍历上面的三个古早集合,且后面的新集合不支持该接口来遍历,

它有两个方法

hasMoreElements()此迭代器是否还有元素

nextElement()返回此迭代器的下一个元素,如果集合为空使用此方法,将抛出异常

在计算机行业有一条规则:加入任何规则都必须慎之又慎,因为以后无法删除规则。

删除原本的规则意味这大换血


死亡诗社

“医药、法律、商业、工程,这些都是高贵的理想,并且是维生的必需条件。但是诗、美、浪漫、爱,这些才是我们生存的原因。”

“Medicine, law, business, engineering — these are noble pursuits and necessary to sustain life. But poetry, beauty, romance, love — these are what we stay alive for.”

这篇关于记录《疯狂Java讲义精粹》划线内容及理解(第6章-java集合概述)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/347724

相关文章

51单片机学习记录———定时器

文章目录 前言一、定时器介绍二、STC89C52定时器资源三、定时器框图四、定时器模式五、定时器相关寄存器六、定时器练习 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出~ 提示:以下是本篇文章正文内容,下面案例可供参考 一、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 定时器作用: 1.用于计数系统,可

Java五子棋之坐标校正

上篇针对了Java项目中的解构思维,在这篇内容中我们不妨从整体项目中拆解拿出一个非常重要的五子棋逻辑实现:坐标校正,我们如何使漫无目的鼠标点击变得有序化和可控化呢? 目录 一、从鼠标监听到获取坐标 1.MouseListener和MouseAdapter 2.mousePressed方法 二、坐标校正的具体实现方法 1.关于fillOval方法 2.坐标获取 3.坐标转换 4.坐

Spring Cloud:构建分布式系统的利器

引言 在当今的云计算和微服务架构时代,构建高效、可靠的分布式系统成为软件开发的重要任务。Spring Cloud 提供了一套完整的解决方案,帮助开发者快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器等)。本文将探讨 Spring Cloud 的定义、核心组件、应用场景以及未来的发展趋势。 什么是 Spring Cloud Spring Cloud 是一个基于 Spring

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

java8的新特性之一(Java Lambda表达式)

1:Java8的新特性 Lambda 表达式: 允许以更简洁的方式表示匿名函数(或称为闭包)。可以将Lambda表达式作为参数传递给方法或赋值给函数式接口类型的变量。 Stream API: 提供了一种处理集合数据的流式处理方式,支持函数式编程风格。 允许以声明性方式处理数据集合(如List、Set等)。提供了一系列操作,如map、filter、reduce等,以支持复杂的查询和转

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

详细分析Springmvc中的@ModelAttribute基本知识(附Demo)

目录 前言1. 注解用法1.1 方法参数1.2 方法1.3 类 2. 注解场景2.1 表单参数2.2 AJAX请求2.3 文件上传 3. 实战4. 总结 前言 将请求参数绑定到模型对象上,或者在请求处理之前添加模型属性 可以在方法参数、方法或者类上使用 一般适用这几种场景: 表单处理:通过 @ModelAttribute 将表单数据绑定到模型对象上预处理逻辑:在请求处理之前

eclipse运行springboot项目,找不到主类

解决办法尝试了很多种,下载sts压缩包行不通。最后解决办法如图: help--->Eclipse Marketplace--->Popular--->找到Spring Tools 3---->Installed。

JAVA读取MongoDB中的二进制图片并显示在页面上

1:Jsp页面: <td><img src="${ctx}/mongoImg/show"></td> 2:xml配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001

Java面试题:通过实例说明内连接、左外连接和右外连接的区别

在 SQL 中,连接(JOIN)用于在多个表之间组合行。最常用的连接类型是内连接(INNER JOIN)、左外连接(LEFT OUTER JOIN)和右外连接(RIGHT OUTER JOIN)。它们的主要区别在于它们如何处理表之间的匹配和不匹配行。下面是每种连接的详细说明和示例。 表示例 假设有两个表:Customers 和 Orders。 Customers CustomerIDCus