1. elastic search的索引为什么叫做倒排索引
因为在传统的索引中,我们建立的是从每个文档到包含在该文档中的所有单词的一个映射。而在倒排索引中,我们建立从每个单词到包含该单词的所有文档的一个映射。也就是说我们对原来的映射关系作了反转,所以被称作倒排索引。这种建索引的方式能够快速地查找包含某个关键词的文档,是全文搜索引擎中的一种经典数据结构。
2. 怎么把用户的输入,例如年龄大于四十,转化为sql,age > 40
将用户的输入转换为SQL查询语句需要进行自然语言处理和语义分析等任务。一种常见的做法是使用自然语言处理工具,例如Stanford CoreNLP、spaCy等,对用户输入的自然语言进行解析,并提取其中的关键词和结构信息。然后,根据提取的信息,生成对应的SQL查询语句。
对于您提到的“年龄大于四十”的查询,一种可能的做法如下:
- 使用自然语言处理工具对查询进行解析,提取其中的年龄和关系词。
- 根据提取的年龄信息和关系词,确定查询属性和比较运算符,即“age”和“>”。
- 构造查询语句,例如“SELECT * FROM users WHERE age > 40”。
需要注意的是,该过程中需要考虑语义的多义性和歧义性等问题,例如“年龄大于四十”可能被解释为“年龄大于40”或“年龄大于等于40”,需要根据具体场景和语境进行解析。(chatGPT)
其实吧,只要能用chatGPT,就很简单。直接把表结构发给他,然后表述需求,他就会生成sql,最关键的一步就这么搞。
3. linux,pam模块
PAM(Pluggable Authentication Modules)是Linux系统中一个可插拔的身份验证框架,允许管理员轻松地自定义和配置身份验证策略。PAM模块是该框架中的一个组成部分,用于提供不同类型的身份验证功能。Linux系统中的许多应用程序都使用PAM模块来完成身份验证。例如,登录程序(login)、密码更改程序(passwd)、SSH服务器(sshd)等。
PAM模块在通过认证前,会按照配置的顺序逐个加载各个模块,并通过对各个模块的返回值进行判断来最终确定是否允许用户进行认证。如果任何一个模块返回失败,则认证失败,不允许用户进行操作。
PAM模块通常存在于/etc/pam.d/目录下,每个应用程序都有一个对应的PAM配置文件。PAM配置文件包含了该应用程序用于身份认证的模块和参数配置信息。系统管理员可以修改这些配置来定制认证策略,并加强系统的安全性。
PAM模块具有高度的灵活性和可定制性,可以使用各种方法进行用户认证,例如基于口令、基于证书、基于网络验证服务等,使得系统管理员可以根据特定需求进行自定义配置,达到最佳的安全性和适应性。
4. mysql联合唯一索引
联合唯一索引是指在一个表中创建的一种索引,它涉及到多个列,并且要求这些列的值的组合必须是唯一的。在MySQL中,可以通过以下语句来创建联合唯一索引:
sqlCopy codeCREATE UNIQUE INDEX index_name ON table_name (column1, column2, ...);
其中 index_name 是索引的名称,table_name 是要创建索引的表名,column1、column2 等是被包含在索引中的列名。创建了联合唯一索引后,如果向表中插入数据时发生违反唯一性约束的情况,则会导致插入操作失败并抛出错误信息。
5. 怎么使用checked exception代替unchecked exception?
使用checked exception代替unchecked exception的主要步骤如下:
1.定义checked exception。首先,在代码中定义需要捕获或处理的异常,将该异常定义为checked exception。可以使用Java中自带的IOException或SQLException等已定义的checked exception,或者自定义一个异常类并继承Exception类。
2.在方法签名中声明checked exception。在方法签名中声明可能抛出的checked exception,即在throws从句中列出异常类型。这将强制调用方显式地处理或传递该异常,避免了unchecked exception未能被处理和传递的情况发生。在方法签名中声明checked exception可以使得开发人员更清楚地了解该方法可能抛出的异常类型。
3.捕获和处理checked exception。在调用可能引发checked exception的方法时,必须在try-catch块中捕获并处理异常,或者在方法签名中再次声明并抛出异常。
4.避免误用unchecked exception。在编写代码时,应该尽量避免使用unchecked exception来代替checked exception。unchecked exception更适合用于表示程序错误、逻辑错误等严重问题,而不是用于表达程序正常运行过程中可能发生的异常情况。
总之,使用checked exception代替unchecked exception可以加强代码的可读性和健壮性。建议在需要显式处理或传递的异常情况下使用checked exception,以便更好地分离关注点、减少系统错误和提高代码质量。
6. @Transactional
7. 再看Spring里面的ClassPathResource.getInputStream(),来获取jar包里面的文件
今天又做文件下载,于是又用到了去年写的那个获取jar包内文件的方法,简单点进去看了一下,有以下n点收获:
- 其实最后调用的还是jdk的ClassLoader里面的方法,但是比起我以前直接去调用,他这个类增加了很多兜底方案,最大限度确保可以获取到输入流。
- 我上次用到的Class Loader里的getResourceAsStream,最终调用到的是URLClassLoader的getResourceAsStream实现。在里面发现了一个WeakHashMap
8. 那就了解一下WeakHashMap
Java的WeakHashMap是一种哈希表(HashMap)的实现,其中键是WeakReference类型的对象,而值可以是任何Java对象。 这意味着在弱键(被持有的对象没有任何强引用)没有被其他部分引用时,该键可以被垃圾回收器回收,并自动从WeakHashMap中删除该键值对。WeakHashMap主要用于缓存或自动清除失效的信息。一般用在缓存场景
- WeakHashMap非同步,数据结构是Entry数组,extends WeakReference
- Java的WeakHashMap中的键(key)是弱引用(WeakReference),当这个键没有被其他强引用持有并且被垃圾回收器标记为无用时,对应的键值对会被自动清除,从而释放相应的空间。这通常发生在下一次垃圾回收时。因此,WeakHashMap中的键可能随时被清除,需要及时进行相应处理,以避免出现预料之外的结果。
- value,会在下一次被访问时或者重新hash时删除
9. Java四种引用类型
-
strong 强引用strong reference是指一种对象引用的方式,当一个对象被一个强引用所持有时,即使系统内存已经不足时,垃圾回收器也不会自动回收该对象,只有当该对象的所有强引用都被释放时,垃圾回收器才会进行回收。在Java中使用最广泛的就是强引用,例如一个对象实例被引用时,通常都是用强引用来进行持有,通过这种方式,程序可以方便地控制对象的生命周期。强引用可以通过“=”赋值操作符给一个对象引用赋值,例如 Object obj = new Object()` 就是一个强引用持有对象 obj。(chatGpt)
-
soft 软引用在java中有个专门的SoftReference类型,软引用的意思是只有在内存不足的情况下,被引用的对象才会被回收。
-
weak 弱引用weak reference和softReference很类似,不同的是weekReference引用的对象只要垃圾回收执行,就会被回收,而不管是否内存不足。
-
phantom 虚引用 PhantomReference 是一种非常弱的对象引用方式。它指向一个对象,并且在垃圾回收器回收该对象时,会将该 PhantomReference 实例添加到一个 ReferenceQueue 中,以便程序可以在垃圾回收完成后进行一些特定的操作。PhantomReference 主要用于跟踪对象的垃圾回收过程,通过它可以在对象真正被垃圾回收之后,进行一些资源回收或清理等操作。例如,可以使用 PhantomReference 跟踪对象的文件或网络连接,在对象被回收时进行相应的资源回收或关闭操作,以避免资源泄露的问题。需要注意的是,PhantomReference 的 get() 方法总是返回 null,因此无法通过该引用直接访问对象的实例变量,只能跟踪对象的回收过程。同时,PhantomReference 也不能像强引用、软引用和弱引用一样直接使用,通常需要与 ReferenceQueue 一起使用。Java 提供了 PhantomReference 类来实现 PhantomReference 引用,例如 PhantomReference phantomRef = new PhantomReference<>(object, referenceQueue)。(chatGpt)
10. WeakReference extends Reference
Java对于简单的情况, 如方法中的产生的局部对象,是不需要程序员来手动置空, 当调用它的方法执行完毕后, 指向它的引用会被GC回收。而复杂一点的情况,比如使用cache,因为cache的对象正是程序运行需要的, 那么只要程序正在运行, cache中的引用就不会被GC,那么随着cache中的引用越来越多, GC无法回收的对象也越来越多, 无法被自动回收,此时就必须有开发者来进行处理回收,显然也违背了java自动回收机制。
对此,java中引入了弱引用(WeakReference)。当一个对象仅仅被weak reference指向, 而没有任何其他strong reference指向的时候, 如果GC运行, 那么这个对象就会被回收。如果存在强引用同时与之关联,则进行垃圾回收时也不会回收该对象。
User user = new User(); WeakReference weakReference = new WeakReference(user); 用之前要先get,因为不知道他还在不在 weakReference.get();
11. 期间还看到synchronized(closeables),WeakHashMap closeables = new WeakHashMap()
因为WeakHashMap线程不安全,synchronized(closeables) 中的 closeables 变量是一个对象引用,用于同步多个线程对 closeables 引用的操作。
Object obj = new Object(); synchronized (obj) { // 当前线程获取了 obj 的锁,并进入到了同步块中执行代码 // 其他线程必须等待当前线程释放锁后才能够继续执行 // 需要注意的是,synchronized 实现了线程间的互斥,但是可能会导致线程的阻塞和性能问题 }
那Closeable是何作用呢?关闭资源!
todo :搞明白为什么要这么关闭资源
问chatGPT:URLClassLoadr中的close为什么要使用weakHashMap存储?(回答真假有待验证,触及到知识盲区了,需要一点时间吸收)
chatGPT答:URLClassLoader 中的 close() 方法实现中,使用 WeakHashMap 存储了该 ClassLoader 所打开的 JarFile 对象和 FileInputStream 对象。主要原因是为了避免因为资源对象没有被正确地释放而导致的内存泄漏问题。
在 Java 应用程序中,通常会使用许多资源对象,例如文件流、网络连接和数据库连接等,如果这些资源对象没有被正确地关闭,将会导致应用程序的内存占用不断增加,从而可能导致 OutOfMemoryError 错误的发生。URLClassLoader 是一个常见的 ClassLoader 实现,在它所加载的类中可能会使用到一些可关闭的资源对象,因此需要在 ClassLoader 关闭时,释放这些资源对象的资源,避免内存泄漏的问题。
使用 WeakHashMap 存储资源对象的好处在于,当资源对象不再被其他对象所持有时,如没有其他强引用指向它,则会被垃圾回收器自动回收,从而释放资源。而使用强引用存储资源对象的话,即使资源对象已经不再被应用程序所使用,但由于仍有强引用持有该对象,因此该对象所占用的内存空间仍然不会被释放,可能会导致内存泄漏的问题。
总之,使用 WeakHashMap 存储资源对象可以较为有效地避免因为资源对象没有被正确地释放而导致的内存泄漏问题,是一种常见的防止内存泄漏的做法。
另外,使用 WeakHashMap 进行资源对象的存储还具有一个额外的好处,即能够避免在资源对象被后续类加载器使用时,由于前一个类加载器已经关闭,导致资源对象被意外关闭的问题。具体来说,当一个类加载器关闭时,它所加载的类及相关的资源都将被释放,如果后续的类加载器仍需要使用这些资源,则可能会导致资源被意外关闭的问题。而使用 WeakHashMap 存储资源对象时,由于 WeakHashMap 中的对象都是使用弱引用进行持有的,因此即使前一个类加载器关闭,也不会影响后续类加载器对资源对象的持有和使用,从而避免了资源被意外关闭的问题。
12. Collections工具类提供了方法可以把List,Map转为线程安全的集合
例如:上面提到的WeakHashMap,也可以这么搞
Map<K, V> map = Collections.synchronizedMap(new WeakHashMap<K, V>());
13.ConcurrentHashMap put与putIfAbsent区别
put与putIfAbsent区别:
put在放入数据时,如果放入数据的key已经存在与Map中,最后放入的数据会覆盖之前存在的数据,
而putIfAbsent在放入数据时,如果存在重复的key,那么putIfAbsent不会放入值。
putIfAbsent 如果传入key对应的value已经存在,就返回存在的value,不进行替换。如果不存在,就添加key和value,返回null
14. java 有几种Lock
Java提供了多种类型的Lock,包括:
- ReentrantLock:可重入锁,支持公平和非公平锁以及中断等待线程。是Java中最常用的锁,提供了可重入锁的机制, 支持公平和非公平锁以及中断等待线程,具有灵活、高效和可扩展等特点,因此被广泛应用于多线程编程中。
- ReentrantReadWriteLock:读写锁,允许多个线程同时读取共享资源,但只允许一个线程写入。读写冲突,写写冲突,但是读读不冲突。
- StampedLock:支持乐观读、悲观读和写锁的机制。
- Condition:条件锁,允许线程等待某个特定条件的出现。
- ReadWriteLock:读写锁,类似于ReentrantReadWriteLock。
- LockSupport:支持线程的挂起与唤醒操作。
以上是Java中常用的锁类型,其中每种锁都有其适用的场景和使用方式。
16. synchronized用在不同地方锁什么?方法锁,类锁
17. 在数据库层面保证数据的完整性还是在应用程序层面?
18. java通过实体类字段创建hashmap
public static HashMap<String, Object> entityToHashMap(EntityClass entityObject) throws IllegalAccessException { HashMap<String, Object> entityHashMap = new HashMap<>(); Class<EntityClass> entityClass = EntityClass.class; Field[] fields = entityClass.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); String fieldName = field.getName(); Object fieldValue = field.get(entityObject); entityHashMap.put(fieldName, fieldValue); } return entityHashMap; } 还可以通过BeanUtils.describe实现19. windows中: sc delete servicename删除服务
在 Windows 操作系统中,sc 是一个命令行工具,用于管理 Windows 系统服务(Services)。sc 命令可以让您在命令行中启动、停止、暂停、继续、查询、配置和删除服务。
22. java怎么通过类的字段名称,获得对应的set方法
在Java中,可以使用反射机制来获得类的字段名称并获取相应的set方法。以下是通过Java反射实现此功能的步骤:
- 获取Class对象:首先,需要获取要操作的类的Class对象。
- 获取Field对象:通过Class对象的getDeclaredField方法可以获取指定名称的字段对象。也可以使用getFields方法获取所有的public字段。
- 获取Method对象:通过class对象的getDeclaredMethod方法可以获取特定名称和参数类型的方法对象。同样地,也可以使用getMethods方法获取所有的public方法。
- 调用set方法:使用得到的method对象调用invoke方法即可执行对应的set方法。
下面是一个示例代码,使用上述步骤来获取并调用指定类的set方法。
javaimport java.lang.reflect.Field; import java.lang.reflect.Method; public class GetSetMethodsDemo { public static void main(String[] args) throws Exception { //获取Class对象 Class<?> clazz = MyClass.class; //获取指定名称的字段对象 Field field = clazz.getDeclaredField("myField"); //构造set方法名称 String setMethodName = "set" + capitalize(field.getName()); //获取指定名称和参数类型的方法对象 Method setMethod = clazz.getDeclaredMethod(setMethodName, field.getType()); //创建一个MyClass对象 MyClass obj = new MyClass(); //调用set方法 setMethod.invoke(obj, "Hello World"); //输出结果,验证是否设置成功 System.out.println(obj.getMyField()); // Hello World } static String capitalize(String str) { return Character.toUpperCase(str.charAt(0)) + str.substring(1); } } class MyClass { private String myField; public void setMyField(String value) { this.myField = value; } public String getMyField() { return myField; } }23. hashmap 调用remove方法之后hashmap会rehash吗
在HashMap中,当调用remove()方法删除一个键值对时,并不会立即触发rehash过程。但是,如果删除操作导致HashMap的负载因子超过了阈值,就会在删除后立即执行rehash。
具体来说,当HashMap的大小(size)达到容量(capacity)的75%时,HashMap会自动扩容并进行rehash操作。而在remove()方法中,仅仅是将被删除的元素标记为已删除,并没有真正地从HashMap中移除该元素,也没有减少HashMap的大小。因此,在删除之后,只有在下一次添加新元素时,HashMap可能需要进行一次rehash以保证负载因子不超过阈值。
另外需要注意的是,由于HashMap的实现使用了链地址法,多个键值对可能会被映射到同一个桶(bucket)中形成一个链表或树。这种数据结构在删除某个键值对时需要对链表或树进行操作,可能会影响到HashMap的性能和结构。因此,当删除某个键值对时,最好先判断该键值对是否存在,并确保正确性和效率。