Lenskit for Java加载CSV遇NoSuchMethodError及加载方法咨询
解决Lenskit加载CSV的NoSuchMethodError问题及CSV/JDBC加载指南
一、先解决你遇到的NoSuchMethodError错误
这个错误是依赖版本不兼容导致的:
- 要么是项目中引入的Guava版本与Lenskit要求的版本不匹配,Lenskit内部调用的
LKFileUtils.byteSource方法在当前Guava版本中不存在或签名不一致; - 要么是Lenskit的各个模块(如
lenskit-core、lenskit-data)版本不一致。
解决步骤:
- 检查依赖管理文件(Maven pom.xml或Gradle build.gradle),确保所有Lenskit相关依赖的版本完全一致,比如所有lenskit开头的依赖都指定同一版本(如3.0)。
- 确保Guava版本符合Lenskit要求:Lenskit 3.x通常依赖Guava 28.1-jre,建议不要手动指定Guava版本,让Lenskit自动管理该依赖,避免版本冲突。
二、正确加载CSV文件的方法
你之前的代码仅初始化了TextEntitySource,但未配置文件格式,也未结合DAO读取数据。完整的CSV加载流程如下:
示例代码(基于Lenskit 3.x)
import org.lenskit.data.dao.file.FileSystemDAO; import org.lenskit.data.dao.file.TextEntitySource; import org.lenskit.data.entities.CommonAttributes; import org.lenskit.data.entities.Entity; import org.lenskit.data.entities.EntityType; import java.io.File; import java.io.IOException; import java.util.List; public class CSVLoader { public static void main(String[] args) throws IOException { // 1. 定义CSV文件路径 File csvFile = new File("D:\\newdocres\\dataset\\item_feature_matrix.csv"); // 2. 配置TextEntitySource,指定文件格式和实体类型 TextEntitySource source = new TextEntitySource(); source.setFile(csvFile.toPath()); // 设置CSV分隔符,默认是制表符,这里改为逗号 source.setDelimiter(","); // 指定实体类型,比如ITEM_FEATURE source.setEntityType(EntityType.forName("ITEM_FEATURE")); // 配置字段映射:CSV列名 -> 实体属性名 source.addAttributeMapping("item_id", CommonAttributes.ITEM_ID); source.addAttributeMapping("feature_1", "feature_1"); source.addAttributeMapping("feature_2", "feature_2"); // 3. 创建FileSystemDAO读取数据 FileSystemDAO dao = FileSystemDAO.create(source); // 4. 读取所有实体 List<Entity> items = dao.query(EntityType.forName("ITEM_FEATURE")).get(); for (Entity item : items) { System.out.println("Item ID: " + item.get(CommonAttributes.ITEM_ID) + ", Feature1: " + item.get("feature_1")); } } }
关键注意点:
- 必须配置
delimiter:默认是制表符(\t),CSV文件需改为逗号(,); - 要指定
entityType和字段映射,否则Lenskit无法识别CSV列对应的实体属性; - 最终需通过
FileSystemDAO加载数据源,而非仅初始化TextEntitySource。
三、使用JDBC加载数据的方法
如果数据存储在数据库中,可使用JdbcEntityDAO读取,步骤如下:
示例代码(以H2内存数据库为例)
import org.lenskit.data.dao.JdbcEntityDAO; import org.lenskit.data.entities.CommonAttributes; import org.lenskit.data.entities.Entity; import org.lenskit.data.entities.EntityType; import org.lenskit.data.entities.EntitySchema; import javax.sql.DataSource; import org.h2.jdbcx.JdbcDataSource; import java.sql.SQLException; import java.util.List; public class JdbcLoader { public static void main(String[] args) throws SQLException { // 1. 配置数据源(实际可替换为MySQL等数据库) JdbcDataSource ds = new JdbcDataSource(); ds.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"); ds.setUser("sa"); ds.setPassword(""); // 2. 定义实体Schema,映射数据库表结构 EntitySchema itemSchema = EntitySchema.create(EntityType.forName("ITEM")) .addAttribute(CommonAttributes.ITEM_ID, long.class) .addAttribute("name", String.class) .addAttribute("category", String.class); // 3. 创建JdbcEntityDAO并注册实体映射 JdbcEntityDAO dao = new JdbcEntityDAO(ds); dao.registerEntity("items", itemSchema); // 4. 查询数据 List<Entity> items = dao.query(EntityType.forName("ITEM")).get(); for (Entity item : items) { System.out.println("Item ID: " + item.get(CommonAttributes.ITEM_ID) + ", Name: " + item.get("name")); } } }
关键注意点:
- 需引入对应数据库的JDBC驱动依赖(如H2的
com.h2database:h2、MySQL的mysql:mysql-connector-java); - 必须注册实体与数据库表的映射关系,指定字段类型和对应关系;
- 确保数据库表结构与实体Schema一致。
内容的提问来源于stack exchange,提问作者Drake Nguyen
相关产品推荐
相关产品推荐

