How to add items to rdflist /rdfcollection dynamically in Jena - java

Is it possible to add items dynamically to a RDFList in Jena?
Something like:
RDFList list = model.createList(new RDFNode[] {});
//string with names of rdf classes
String[] parts = list.split("-");
for(int i = 0; i<parts.length; i++){
OntClass oclass = model.getOntClass("http://example.org/"+parts[i]);
list.add(oclass);
}
I'm getting
com.hp.hpl.jena.rdf.model.EmptyListUpdateException: Attempt to add() to the empty list (rdf:nil)
Thanks in advance

Without seeing all of your code and what some of the values are, we can't be sure what's happening, but I think the problem here is that you can't use RDFList#add with an empty list, and I think that's what you're creating at the start. Since you're creating a list with no elements, you should be getting rdf:nil back, which is the empty list. Note that the documentation for RDFList#add says:
If this list is the empty (nil) list, we cannot perform a side-effecting update without changing the URI of this node (from rdf:nil) to a blank-node for the new list cell) without violating a Jena invariant. Therefore, this update operation will throw an exception if an attempt is made to add to the nil list. Safe ways to add to an empty list include with(RDFNode) and cons(RDFNode).
You didn't mention whether you're getting that exception or not.
In your case, I think the easiest thing to do would be to create the array of OntClasses, and then just create the list from them. That is, you could do something like (untested):
String[] parts = list.split("-");
RDFNode[] elements = new RDFNode[parts.length];
for(int i = 0; i<parts.length; i++){
elements[i] = model.getOntClass("http://example.org/"+parts[i]);
}
RDFList list = model.createList(elements);
Alternatively, if you want to use with, as mentioned in the documentation, you'd do something like (again, untested):
RDFList list = model.createList(new RDFNode[] {});
//string with names of rdf classes
String[] parts = list.split("-");
for(int i = 0; i<parts.length; i++){
OntClass oclass = model.getOntClass("http://example.org/"+parts[i]);
list = list.with(oclass);
}
For a bit more about this, you might find this answer of mine and the comments on it relevant. You're not the first one to have had a bit of a struggle with RDFLists.

Related

How to convert an object to a set?

so I have a set named "all" that contains objects Doc. Then I have another set called "partDocs" that contains other sets that contains Doc. Let's say that "all" contains = [Doc1, Doc2, Doc3]. I want partDocs to contain those sets like: [[Doc1], [Doc2], [Doc3]]. How can I do that?
I tried
Set<Doc> all = new HashSet<Doc>(); // contains [Doc1, Doc2, Doc3]
Set<Set<Doc>> partDocs = new HashSet<Set<Doc>>();
Set<Doc> set2 = new HashSet<Doc>();
for (i = 0; i < all.size(); i++) {
set2.clear();
set2.add(all.stream().toList().get(i)); // adds the i.th element of the all set
partDocs.add(set2);
}
However when I do this, partDocs only has the last element of the all set, because set2 is always changing, and its last value is [Doc3]
I also tried doing below, but its syntax is wrong
for (i = 0; i < all.size(); i++) {
partDocs.add(Set<allDocuments.stream().toList().get(i)>);
}
Does anyone have any idea about how to implement this?
I don't know if you actually want to do this. It seems like very confusing code but try the following:
Set<Set<Doc>> partDocs = new HashSet<Set<Doc>>();
Set<Doc> all = new HashSet<>();
for(Doc doc : all) {
partDocs.add(Set.of(doc));
}
And now you have a set (partDocs) that contains sets which contain docs
The invalidation of set2 is flawed.
Instead of
set2.clear();
it should be
set2 = new HashSet<Doc>();
This particular bug may be easier to understand if we use a list for partDocs
List<Set<Doc>> partDocs = new ArrayList<Set<Doc>>();
which results in
[[Doc3], [Doc3], [Doc3]]
Essentially, we are adding the same Set to the List and since we are using the same reference, consecutive calls to set2.clear() and set2.add() will affect both the local variable and the Set in the List.
Going back to partDocs being a Set, it will end up with only one entry, because a Set guarantees to not contain duplicate values and three identical instances are of course duplicates.
So, to fix this bug, we must ensure that the three objects added to partDocs are truly distinct, which is accomplished (partly) by the new invalidation routine
set2 = new HashSet<Doc>();
and otherwise by the fact that we add a different element to it each time.

How to remove item from ArrayList if condition in other ArrayList is true

I have a JTable with three columns, each of which is filled with an array made from an ArrayList. I am trying to make a search system, where the user will search for a value in the first column, and the rows of the JTable will filter out, so that only the rows that contain the specified String from the search box show up on the table after a button is pressed. On another table, this worked by filtering the ArrayList used using this loop:
String s = searchBar.getText();
ArrayList<String> fn = new ArrayList<>();
fn.addAll(names); //names is the arraylist that contains all the values that will be filtered
for(Iterator<String> it = fn.iterator(); it.hasNext(); ) {
if (!it.next().contains(s)) {
it.remove();
}
This code works to filter out the array, but what I am trying to do is filter 3 ArrayLists based on only if one of the ArrayLists does not contain the s String.
I tried doing this:
String s = searchBar.getText();
ArrayList<String> fn = new ArrayList<>();
ArrayList<String> fp = new ArrayList<>();
fn.addAll(names); //names is the arraylist that contains all the values that will be filtered
fp.addAll(numbers)//one of the other arraylists that I want to filter
for(Iterator<String> it = fn.iterator(), itp = fp.iterator(); it.hasNext() && itp.hasNext(); ) {
if (!it.next().contains(s)) {
itp.remove();
it.remove();
}
When I run this code I get a Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException on the line where I write "itp.remove();".
Is there a way I can remove from both the arrays based on only one of them?
I'm happy that you fix your exception. Anyway, when I said about back iteration I meant something like that
Firstly, Some of check like
if(fn.size()==fp.size()){
// and after that go to delete.
for (int i=fn.size(); i>0;i--) {
if (fn.contains(s)) {
fn.remove(i);
fp.remove(i);
} }}
Anyway, your and my method isn't good for multithreading, because ArrayList doesnt't concurrent object also it's remove method
So I managed to fix it by using the remove method from the ArrayList instead of the remove method from the Iterator. I know this isn't the recommended way of doing it, but it seems to not have brought any negatives with it, so I will keep it for now.
The code I used is:
int i = 0;
for (Iterator<String> it = fn.iterator(); it.hasNext(); i++) {
if (!it.next().contains(s)) {
it.remove(); //Iterator's remove
fp.remove(i);// ArrayList's remove which avoids the error
}
}
Thank you to all who helped

Iterate through an list of objects and run a function for each - Java

I'm wondering for the simplest method for how to run a specific function for each object in an array (or other list type)
My goal is to be able create a list of objects, and have each object run a specific function as it passes through the iterator.
I've tried a for loop on an arraylist
for (int i = 0; i < testList.size(); i++)
{
this = textList.get(i);
this.exampleFunction();
}
But this gives me a 'Variable expected' error
Assuming you're using Java 8+, and you have a Collection<TypeInList> you could call Collection.stream() and do a forEach on that. Like,
testList.stream().forEach(TypeInList::function);
Your current approach is trying to do things with this that cannot be done. It could be fixed like,
for (int i = 0; i < testList.size(); i++)
{
TypeInList that = testList.get(i); // this is a reserved word.
that.function();
}
or
for (TypeInList x : testList) {
x.function();
}
There are multiple ways to iterate through a list, but the easiest I personally find is like this:
Assuming that your list contains String objects e.g.:
List<String> list = new ArrayList();
list.add("Hello");
list.add("World");
for(String current : list){
System.out.println(current);
}
The loop will iterate twice, and console will output the following:
Hello
World
This approach doesn't rely on indexes (as how you're using it in your question), as such I find it easy to use for iterating through a single list.
However the disadvantage is that if you have 2 separate lists that you would like to iterate through, the lack of indexes makes it a bit more complicated. The easier approach for iterating through multiple lists would be using the traditional approach, something like this:
for(int i=0; i<list.size(); i++){
int x = list1.get(i);
int y = list2.get(i);
}
As such your use-case really determines the ideal method you can adopt.

Delete file from a file list

I am creating an android application, and I created a list of available files in the internal memory with this instruction:
final String[] files =fileList();
I need to remove a file from this list and I don't know how, can you help me?
To "remove" something you can just set it back to null, or you can do it the hard way with a loop that shifts everything behind it up a place.
public void remove( int index ) {
for(int i=index; i<sarr.length()-1; i++) {
sarr[i] = sarr[i+1]
}
sarr[sarr.length()-1] = null;
System.out.println("Removed!");
}
When using primitive arrays like this, there is no removal method. If you built a more complex datatype you could have the "remove" method available to you.
Use a List<String> instead. That way you can remove the file that you want using the remove() method.
index = 0//location of item to be removed, with the first item in the list at 0
List<String> files = Arrays.asList(getFiles());
files.remove(index)
in this example, index is the location of the item that you want to remove. Alternatively, you could do this instead
item = "fileLocation";
List<String> files = Arrays.asList(getFiles());
files.remove(item)

How to "propagate" the sorting of an `ArrayList<String>` to another one?

I have multiple ArrayList<String>s "linked" into a custom adapter I'm using to build a list view.
Now suppose they are just two in total, to simplify.
I want to sort one of them and then have this new order reflected into the other one, in order to maintain the list consistent.
This is what I was thinking to do and doesn't work, ending with an IndexOutOfBoundsException: Invalid index 0, size is 0 at the line signed with *.
// initial declarations:
List<String> filenameEntries = new ArrayList<String>();
List<String> idEntries = new ArrayList<String>();
/* various operations that fill
the two ArrayList here... */
// sorting:
List<String> oldFilenameEntries = new ArrayList<String>();
List<String> oldIdEntries = new ArrayList<String>();
oldFilenameEntries = filenameEntries;
oldIdEntries = idEntries;
idEntries.clear();
Collections.sort(filenameEntries);
for (int i = 0; i < filenameEntries.size(); i++ ) {
for (int j = 0; j < oldFilenameEntries.size(); j++ ) {
if (oldFilenameEntries.get(j) == filenameEntries.get(i)) {
idEntries.add(oldIdEntries.get(j)); // *
}
}
}
My idea was to search into the old ArrayList for every element from the new one, and then use this "old" index to re-polulate the other ArrayList.
(I have the restriction that the other "sorted" ArrayList must be again idEntries. This is way I did this sort of transfer)
Any suggestion?
Thanks.
EDIT:
I thought it was a sorting issue and then came out I missed the right way to make a copy for the ArrayLists. Thanks to everyone that pointed out that the error was at
oldFilenameEntries = filenameEntries;
oldIdEntries = idEntries;
and why.
I accepted the answer that pointed me more quickly to the solution.
I removed the two lines above and changed the previous into
List<String> oldFilenameEntries = new ArrayList<String>(filenameEntries);
List<String> oldIdEntries = new ArrayList<String>(idEntries);
and from what I can see ATM all seems to work as expected.
The issue is the assignment: oldIdEntries = idEntries; this is causing both references to point to same list so when you do idEntries.clear(); you have cleared the one list to which both are pointing. You need to make a copy of the list not just assign the reference.
Collections.copy
Lists.copy
ImmutableList.copy()
The problem is in these 2 lines:
oldFilenameEntries = filenameEntries;
oldIdEntries = idEntries;
After this, both old... and original variables point to the same list. Then you call idEntries.clear(). This clears both idEntries and oldIdEntries since they point to the same list.
For this to work, you need to copy the list instead of just assigning it. You could use Collections.copy(). Here is an example:
Java Collections copy list - I don't understand
On a different note, this approach seems too complex - but it's also not very clear what you are trying to accomplish so I can't suggest a better way.
Iterate over the soreted list, clone each object and then add it to the new array list
Two issues:
One:
oldFilenameEntries = filenameEntries;
oldIdEntries = idEntries;
Now, both old and new entries point to the same list.
Then, idEntries.clear().
This clears both old and new entries.
If you want to do this somehow, use Collections.copy()
Two:
If you're just going to check for equality, I don't see why you need to have two for-loops, and have both sorted.
You could just do this:
for (int i = 0; i < filenameEntries.size(); i++ ) {
if (oldFilenameEntries.contains(filenameEntries.get(i)) {
idEntries.add(oldIdEntries.get(j)); // *
}
}
}
NOTE: as I don't know what the original point of your code was, and equality checking was all I could infer from your snippet, I'm suggesting this.

Categories