List添加Item时, 如何去判断某个字段, 并且保证字段数据不重复性

本文介绍了一种在SharePoint List中防止特定字段数据重复的方法。通过修改SCHEMA.XML文件和利用Microsoft.XMLHTTP对象发送验证请求,确保了数据的一致性和唯一性。此方案适用于多个List,易于部署且无需额外编译。

List添加Item时, 如何去判断某个字段, 并且保证字段数据不重复性

  SharePoint中如何使得用户不能通过对WSS的List中添加或修改使得某个指定字段存在重复数据。并需要尽可能满足以下需求:


1) 希望解决方案比较简单,并且易于部署(客户希望在30分钟内能完成部署)

2) 希望在部署过程中不需要重新编译任何工程

3) 有一定的通用性,不能针对一个特定的List开发一个组件

---------------------------------------------------------------
目前研究的结果:

研究结果及解决方案(以新建记录为例)

==================

系统实现思路

=======





由于所涉及的步骤牵涉修改WSS默认的模板和JavaScript代码,所以请在测试环境中完成下述步骤并备份相关信息。



1. 当用户新建记录、提交表单时,WSS会首先调用ClickOnce()函数(请在新建记录页面点击右键,查看HTML源文件),然而,ClickOnce()并不存在NewForm.ASPx文件中,而是在相应List模板的SCHEMA.XML中(如,我们使用Customized List,List模板的路径是C:/Program Files/Common Files/Microsoft Shared/web server extensions/60/TEMPLATE/1033/STS/LISTS/CUSTLIST)且所有WSS List都会调用OWS.JS文件,引用其中的JavaScript。表单会提交到/_vti_bin/owssvr.dll上,最终插入数据库。这是默认的表单提交过程。



2. 为了在期间加入定制的代码,检查是否会产生重复数据。我们可以采取以下几种通讯方式:





a) 在SCHEMA.XML中拦截 ClickOnce()函数,使用Microsoft.XMLHTTP对象向Server端的ASPX页发送POST请求,并接收Server端的回传数据,SCHEMA.XML的作用域是一个特定的List。在本样例中,我们选用这种方式



b) 由于在提交表单的流程中,SCHEMA.XML中定义的ClickOnce()函数最终会调用OWS.JS中的程序段,虽然,我们可以在OWS.JS的有关函数中拦截默认的提交流程,并向Server端发送请求,但是,我们不推荐这种方式,因为修改OWS.JS可能影响到多个List。只有在特定的条件下,才使用这种全局的方式,并且希望您进行全面的测试。



c) 前两种方式是在客户端向服务端发送请求,进行验证,如果需要全部PostBack回服务器端进行认证,请使用FrontPage 2003,打开NewForm.ASPx,在输入WebPart上点右键,并选择“Customized SharePoint List Form”菜单项,将输入WebPart转换为表格模式,如下所示:



此时我们可以使用传统ASP.NET窗体的方式,在上面添加自定义的输入栏位和提交按钮,并可以提交到特定的后台页面。这种方式需要对每个List的NewForm.ASPX分别处理。



3. 服务器端是一个ASP.NET页面,它将接收ListID(List的Guid)和FieldValue(需要字段填充值),ASP.NET页面会读取一个XML配置文件,并比对其中的ListID,用以决定是否需要对本List进行验证(针对多个List的通用解决方案)。如果需要验证,则从XML配置中读取需要验证的字段名称等信息,并进行查询。无论成功与否ASP.NET页面会将返回信息回写到客户端。



4. 客户端的Microsoft.XMLHTTP对象获得回写的字符串后进行必要的解析,并决定相应的流程。





具体实现步骤

=======

1. 本样例中将使用Customized List模板为例,在C:/Program Files/Common Files/Microsoft Shared/web server extensions/60/TEMPLATE/1033/STS/LISTS目录中复制CUSTLIST目录,并命名位LIANGMING

2. 打开上层目录下的XML目录(C:/Program Files/Common Files/Microsoft Shared/web server extensions/60/TEMPLATE/1033/STS/XML)中的ONET.XML,并找到<ListTemplates>片段,插入如下黑斜体部分,将Type设为小于1000,且和当前List的Type字段没有重复的数值,并保持Name域的信息和复制的目录名称相同。

<ListTemplates>

<ListTemplate Name="custlist" DisplayName="Custom List" Type="100" BaseType="0" OnQuickLaunch="TRUE" SecurityBits="11" Description="Create a custom list when you want to specify your own columns. The list opens as a Web page and lets you add or edit items one at a time." Image="/_layouts/images/itgen.gif"></ListTemplate>

<ListTemplate Name="LIANGMING" DisplayName="Liang Ming Customized List" Type="500" BaseType="0" OnQuickLaunch="TRUE" SecurityBits="11" Description="LIANG MING" Image="/_layouts/images/itgen.gif"></ListTemplate>



3. 在命令窗口中调用IISReset,重启IIS服务



4. 在新建List页面(任何对List模板的修改,必须新建一个List才可以看到结果)我们会发现有个LIANGMING的List模板





5. 打开List模板目录下的SCHEMA.XML,添加如下代码:

function CheckField()

{

var fldValue;

for(i=0;i<frm.form.elements.length;i  )

{

//查找特定字段的值(需要检查的值),此处使用title属性,可根据实际情况修改

if(frm.form.elements.title == "Employee ID"){

fldValue = frm.form.elements.value;

break;

}

}

//默认List的GUID存放在Hidden的onetidIOHidden字段中

var lstId = document.getElementById("onetidIOHidden");

//使用Microsoft.XMLHTTP向服务端的页面发送请求

var XMLhttp = new ActiveXObject("Microsoft.XMLHTTP");

XMLhttp.Open("POST","/_layouts/CheckField/DoCheck.ASPx?ListID="   lstId.value   "
<think> 首先,用户的问题是:"我想查找在Java 8中如何根据List中对象的字段判断是否有重复数据的方法"。用户提供了几个引用,但这些是参考,我需要基于用户的真正需求和我的知识来回答。 用户的需求是:检查一个List中的对象是否基于某个字段重复数据。即,是否有多个对象具有相同的字段值。 关键点: - 输入:一个List<T>,其中T是一个对象类型。 - 基于一个字段值(如User对象的getUserid())来判断是否有重复。 - 输出:一个布尔值或其他指示是否有重复。 用户引用的内容: - 引用[1]:是关于重的,使用TreeSet和Comparator来重复。 - 引用[2]:是关于获取重复数据的个数。 - 引用[3]:是关于基于字段重的。 用户明确说:"上述引用仅供参考",所以我能直接复制这些;我需要提供一个判断是否有重复的方法。 从引用和用户的问题中,我可以提取一些思路: - 使用Java 8的Stream API。 - 基于字段分组,然后检查是否有组的size > 1。 好的方法来检查是否有重复: 1. 使用Stream的groupingBy将对象按字段分组。 2. 然后检查是否有任何组的大小大于1。 步骤: - 创建流:list.stream() - 分组:Collectors.groupingBy(User::getUserid) - 然后:检查分组后的map中,是否有值(即列表)的大小大于1。 代码草图: ```java boolean hasDuplicates = list.stream() .collect(Collectors.groupingBy(User::getUserid)) .values() .stream() .anyMatch(group -> group.size() > 1); ``` 或者更简洁: ```java boolean hasDuplicates = list.stream() .map(User::getUserid) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) .values() .stream() .anyMatch(count -> count > 1); ``` 在第二个版本中,我直接映射到字段值,然后分组计数。这样更高效,因为需要存储整个对象。 用户可能需要计数,只需要布尔值。 另一个简单方法:比较distinct的大小和原列表大小。 - 如果基于字段的distinct元素个数小于原列表大小,则有重复。 - 例如:long distinctCount = list.stream().map(User::getUserid).distinct().count(); - boolean hasDuplicates = distinctCount < list.size(); 这更简单高效,因为它需要全部分组,只需计数。 distinct计数方法: ```java boolean hasDuplicates = list.size() != list.stream().map(User::getUserid).distinct().count(); ``` 是的,如果大小同,则有重复。 现在,回答结构: - 系统指令说:回答结构清晰,帮助用户逐步解决问题。 - 使用中文。 - 生成相关问题。 - 引用末尾添加标识(用户提供的引用),但用户说那些是参考,所以如果有引用,就自然地添加。 用户没有提供新的引用,所以我应该基于知识回答。 最后,生成相关问题。 完整回答结构: 1. 解释方法。 2. 提供代码示例。 3. 说明优点。 4. 生成相关问题。 使用中文。 代码示例需要符合LaTeX格式?指令说:行内数学表达式用$...$,但代码是代码块,所以需要LaTeX。指令有示例使用代码块```python```,所以类似地,用```java```。 在Java中,需要LaTeX数学。 现在,回答问题: - 方法1:使用distinct计数。 - 方法2:使用分组。 我推荐distinct计数方法,因为它更简单。 代码示例: ```java import java.util.List; import java.util.stream.Collectors; public class DuplicateChecker { public static <T, R> boolean hasDuplicatesByField(List<T> list, Function<T, R> fieldExtractor) { long distinctCount = list.stream() .map(fieldExtractor) .distinct() .count(); return distinctCount < list.size(); } } // 使用示例 List<User> userList = ...; // 用户的列表 boolean hasDuplicates = hasDuplicatesByField(userList, User::getUserid); ``` 或者直接写内联。 用户可能需要泛型方法,可以直接写。 为了清晰,提供一个示例。 现在,生成相关问题: - 类似于示例:"相关问题" - 例如: 1. 如何获取重复数据的列表? 2. 如何基于多个字段判断重复? 3. Java 8中重的其他方法? 参考系统指令中的示例。 最后,添加引用标识:用户提供了引用[^1], [^2], [^3],但用户说它们是直接需求,所以如果我在回答中提到它们,就添加。但在这个问题中,我直接引用它们,所以可能需要添加引用标识。用户说:"上述引用仅供参考",所以我应该基于那些思路回答,但强制引用。 在回答中,我可以简要提到参考了重方法。 回答开头:参考您提供的引用和相关Java 8知识,我将解释如何判断是否有重复数据。 结尾:自然地添加引用。 为了安全,在提到添加引用。 现在,写回答。 </think> ### Java 8中根据List对象字段判断是否有重复数据的实现方法 在Java 8中,判断一个List中对象是否基于某个字段重复数据,可以使用Stream API高效实现。核心思路是:基于字段提取值,比较重后的元素个数是否小于原列表大小。如果大小同,则说明有重复数据。下面我将逐步解释实现方法,并提供代码示例。 #### 步骤详解 1. **映射字段值**:首先使用`map()`方法将对象列表映射到指定字段的值(如`User::getUserid`),得到一个字段值的流。 2. **计算重计数**:使用`distinct()`方法重复值,然后通过`count()`统计重后的元素个数。 3. **比较大小判断重复**:如果重后的元素个数`distinctCount`小于原列表大小`list.size()`,则说明有重复数据;否则无重复。 这种方法间复杂度为O(n),空间复杂度为O(n),适用于大多数场景,且代码简洁。 #### 代码示例 以下是一个完整的Java实现。假设有一个`User`类,包含字段`userid`,我们需要检查`userList`中是否有基于`userid`的重复数据。 ```java import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; public class DuplicateChecker { public static void main(String[] args) { // 示例List(包含重复userid) List<User> userList = List.of( new User(1, "Alice"), new User(2, "Bob"), new User(1, "Alex") // userid=1重复 ); // 检查是否有基于userid的重复数据 boolean hasDuplicates = hasDuplicatesByField(userList, User::getUserid); System.out.println("是否存在重复数据: " + hasDuplicates); // 输出: true } /** * 通用方法:判断List中基于指定字段是否有重复数据 * @param list 对象列表 * @param fieldExtractor 字段提取函数(如 User::getUserid) * @return true表示有重复,false表示无重复 */ public static <T, R> boolean hasDuplicatesByField(List<T> list, Function<T, R> fieldExtractor) { if (list == null || list.isEmpty()) { return false; // 空列表或无元素,视为无重复 } long distinctCount = list.stream() .map(fieldExtractor) // 映射到字段.distinct() // .count(); // 计数重后的元素 return distinctCount < list.size(); // 比较大小 } } // User类定义 class User { private int userid; private String name; public User(int userid, String name) { this.userid = userid; this.name = name; } public int getUserid() { return userid; } public String getName() { return name; } } ``` #### 方法说明 - **代码解析**: - `hasDuplicatesByField`方法使用泛型`<T, R>`,适用于任何对象类型(如`User`)和字段类型(如`Integer`)。 - 通过`fieldExtractor`(如`User::getUserid`)提取字段值,避免硬编码,提高可重用性。 - 使用`distinct().count()`组合高效重并计数,无需存储分组数据,内存占用更优。 - **优点**: - 一行核心代码即可实现:`list.stream().map(fieldExtractor).distinct().count() < list.size()`[^1]。 - 相比分组方法(如`groupingBy`),此方法更简洁高效,特别适合只判断是否存在重复的场景。 #### 注意事项 - **空值处理**:如果字段值可能为`null`,需在`map`前添加过滤(如`.filter(Objects::nonNull)`),否则`distinct()`会包含`null`作为有效值。 - **性能建议**:对于大列表,此方法性能良好,但若字段值分布高度重复,可使用`Collectors.toSet()`替代`distinct()`进一步提升效率。 - 参考您的引用,类似重逻辑可扩展用于获取重复数据列表或计数[^1][^2]。 如果您需要修改字段、处理多字段判断或其他场景,我可以进一步优化代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值