Linked List Optimization - java

I'm working on this program that emulates restriction enzymes and DNA splicing. I'm using DnaSequenceNode[s] as linked list nodes.
I have a problem with one of the function in my code, cutSplice() is supposed to create a new DnaStrand that is a clone of the current DnaStrand, but with every instance of enzyme replaced by splicee.
For example, if the LinkedDnaStrand is instantiated with "TTGATCC", and
cutSplice("GAT", "TTAAGG") is called, then the linked list should become something like (previous pointers not shown):
first -> "TT" -> "TTAAGG" -> "CC" -> null
My function works. However, my method cutSplice() takes more than 80 seconds to splice 200 DNAs. I'm supposed to bring that 80 seconds to 2 seconds.
This is all my code for the class : LinkedDnaStrand.java
And here's the code for the method cutSplice()
public DnaStrand cutSplice(String enzyme, String splicee) {
DnaStrand newStrand = null;
String original_Dna = this.toString();
String new_Dna = original_Dna.replaceAll(enzyme, splicee);
String[] splicee_split = new_Dna.split(splicee); // splits the new DNA string DnaStrand
newStrand = null;
int i = 0;
if (original_Dna.startsWith(enzyme)) {
newStrand = new LinkedDnaStrand(splicee);
} else {
newStrand = new LinkedDnaStrand(splicee_split[0]);
newStrand.append(splicee);
}
for (i = 1; i < splicee_split.length - 1; i++) {
String node = splicee_split[i];
newStrand.append(node);
newStrand.append(splicee);
}
newStrand.append(splicee_split[splicee_split.length - 1]);
if (original_Dna.endsWith(enzyme)) {
newStrand.append(splicee);
}
return newStrand;
}
Does anybody see anything that could make a critical difference on the time this function takes to process 200 DNAs sample?

Well, it is comfortable to use the string methods, but you are losing time in converting to the string, back to sequence, and (as pointed out in the previous comments) with the regex based string functions.
It will certainly consume less time to operate on the linked list directly, although this will require you to implement the replacement algorithm yourself:
#Override
public LinkedDnaStrand cutSplice(String enzyme, String splicee)
{
LinkedDnaStrand strand = new LinkedDnaStrand();
DnaSequenceNode end = null;
DnaSequenceNode begin = top;
int pos = 0;
DnaSequenceNode tmpStart, tmpEnd;
for (DnaSequenceNode current = top; current != null; current = current.next)
{
if(current.value != enzyme.charAt(pos))
{
tmpStart = tmpEnd = new DnaSequenceNode(begin.value);
for (DnaSequenceNode n = begin.next; n != current.next; n = n.next)
{
DnaSequenceNode c = new DnaSequenceNode(n.value);
tmpEnd.next = c;
c.previous = tmpEnd;
tmpEnd = c;
}
}
else if(++pos == enzyme.length())
{
tmpStart = tmpEnd = new DnaSequenceNode(splicee.charAt(0));
for (int i = 1; i < splicee.length(); ++i)
{
DnaSequenceNode c = new DnaSequenceNode(splicee.charAt(i));
tmpEnd.next = c;
c.previous = tmpEnd;
tmpEnd = c;
}
}
else
{
continue;
}
if(end == null)
{
strand.top = end = tmpStart;
}
else
{
end.next = tmpStart;
tmpStart.previous = end;
}
end = tmpEnd;
begin = current.next;
pos = 0;
}
return strand;
}
I do not claim that there is not any opportunity to further optimize, but this should be a lot faster as the original version. I tested it successfully with the example you gave, if you yet find a bug, feel free to fix it yourself...
Note 1: I did explicitely create a new sequence from the string (instead of using the constructor) to get the end of the sequence without having to iterate over it again.
Note 2: I assumed existing a constructor DnaSequenceNode(char value) and DnaSequenceNode having a member public char value. You might have to adjust the code appropriately if any of these assumptions fails.

Related

Java - outOfMemory - Heap Space

So I'm trying to complete an exercise where I've been asked to implement a method that does a binary search in an ArrayList of objects. From the exercise:
Binary search
In the Main-class, implement a method public static int binarySearch(ArrayList<Book> books, int searchedId), which searches the list it received as a parameter, for a book with an id variable that matches the value of searchedId variable it received as a parameter. If that book is found the method, should return the index it's located at, in the list it received as a parameter. If the book isn't found, the method should return the value -1.
The method must be implemented as a binary search, which assumes the list is ordered. You should also assume, that the ids towards the beginning of the list, are always smaller than the ids towards the end of the list.
I have created two methods, one to check whether the arraylist is sorted (isItSorted) and the other one that will perform the binary search if the aforementioned method evaluates to true (binarySearch). Please see below:
public static boolean isItSorted(ArrayList<Book> books) {
ArrayList<String> boo = new ArrayList<>();
String isItSorted = "";
for (int i = 0; i < books.size(); i++) {
for (int j = i + 1; j < books.size(); j++) {
if (books.get(i).getId() < books.get(j).getId()) {
isItSorted = "true";
boo.add(isItSorted);
} else {
isItSorted = "false";
boo.add(isItSorted);
}
}
}
if (!(boo.contains("false"))) {
return true;
}
return false;
}
public static int binarySearch(ArrayList<Book> books, long searchedId) {
if (searchedId < 0 || books.isEmpty()) {
return -1;
} else if (isItSorted(books)) {
int start = 0;
int end = books.size() - 1;
int middle = (start + end) / 2;
if (books.get(middle).getId() == searchedId) {
return middle;
} else if (books.get(middle).getId() > searchedId) {
end = middle - 1;
} else if (books.get(middle).getId() < searchedId) {
start = middle + 1;
}
while (start <= end) {
if (books.get(start).getId() == searchedId) {
return start;
}
start++;
}
}
return -1;
}
Inside these java files, there's a test package that tests whether my solution is correct or not. While 95% of the tests are successful, when it reaches the method below (where it compares the time of execution compared to my other method (linear search)), I get the error Java outOfMemory heap Space.
I use NetBeans. I've already tried the JVM commands.
My solution seems to work with every number of objects I've tried, so perhaps there's something wrong with the test code below?
#Test
#Points("07-05.2")
public void binarySearchIsFasterThanLinearSearch() throws Throwable {
ArrayList<Book> books = generateBooks(10000);
Collections.sort(books, (k1, k2) -> k1.getId() - k2.getId());
int searched = 1000001;
long bSearchStart = System.nanoTime();
int binarySearchId = Searching.binarySearch(books, searched);
long bSearchEnd = System.nanoTime();
assertTrue("When binary search does not find what was searched for, it must return -1", binarySearchId == -1);
long lSearchStart = System.nanoTime();
int linearSearchId = Searching.linearSearch(books, searched);
long lSearchEnd = System.nanoTime();
assertTrue("When linear search does not find what was searched for, it must return -1", linearSearchId == -1);
long bSearchTime = bSearchEnd - bSearchStart;
long lSearchTime = lSearchEnd - lSearchStart;
assertTrue("When there are 10000 books to search, and the searched book is not found, binary search should be a lot faster than linear search. Current this isn't so", bSearchTime * 2 < lSearchTime);
}
ArrayList<String> boo = new ArrayList<>();
String isItSorted = "";
for (int i = 0; i < books.size(); i++) {
for (int j = i + 1; j < books.size(); j++) {
if (books.get(i).getId() < books.get(j).getId()) {
isItSorted = "true";
boo.add(isItSorted);
} else {
isItSorted = "false";
boo.add(isItSorted);
}
}
}
Adds on the order of 100 million items to the ArrayList boo.
If you want to check if something is sorted you can use much simpler code:
Book prev = books[0];
for (int i = 1; i < books.size(); i++) {
if (prev.getId() > books[i].getId())
return false;
}
return true;
But you shouldn't need to call it inside binarySearch() because that will defeat the purpose of binarySearch() and make it as slow as linearSearch().

How can I access objects in a loop?

I am trying to hand over the position value of my object 'next' to the next 'next' object. Is it possible to write this code as a loop and scale it by n?
next.next.next.next.pos.y = next.next.next.pos.y;
next.next.next.next.pos.x = next.next.next.pos.x;
next.next.next.pos.y = next.next.pos.y;
next.next.next.pos.x = next.next.pos.x;
next.next.pos.y = next.pos.y;
next.next.pos.x = next.pos.x;
next.pos.x = pos.x;
next.pos.y = pos.y;
I guess you want something like this:
while(obj.next != null) {
obj.next.pos.x = obj.pos.x;
obj.next.pos.y = obj.pos.y;
obj = obj.next;
}
Later edit:
Sorry, I misunderstood your question.
You could then use a list to solve this issue. It's not the most performant way to do it but I will work.
List<Obj> objs = new ArrayList<>();
objs.add(obj);
// Add everything to a list
while(obj.next != null) {
objs.add(obj.next);
obj = obj.next;
}
// Walk the list in the reverse order
for(i = objs.size() - 1; i > 1 ; i--) {
objs[i].pos.x = objs[i - 1].pos.x;
objs[i].pos.y = objs[i - 1].pos.y;
}

JAVA check statement to get value on first execution of statement

HashMap intermediateIdMap = new HashMap(d_idMap.size());
int linkCounter = 0;
for (Iterator it = d_idMap.entrySet().iterator(); it.hasNext(); )
{
Map.Entry me = ((Map.Entry) it.next());
long oldId = (Long) me.getKey();
MapObject mo = d_mc.findMapObject(oldId);
if (mo != null && !isMetaDataType(mo)
&& (IdSpace.isTransient(mo.id()) || d_updateAllIds
|| isNegativeIdUpdate(mo.id())))
{
int transientId = d_idGenerator.getNewId();
I need to get the first transientId when its executed for the very first time and the Id it sets and also the last Id i.e MIN_TRANSIENT and MAX_TRANSIENT
I tried changing the Data Structure to LinkedHashMap which would have given me the 1st and Last element easily but i guess seniors dont want me to change the ds, do you guys help me find an another way
public synchronized int getNewId()
{
// Contract.precondition("Within range", d_currentId <= d_range);
// CMSDL-3988 - recycle/reset the currentId once max reached
if(d_currentId>d_range)
d_currentId=MIN_TRANSIENT;
return d_currentId++;
}
If you need changes for a reason, you should be allowed to do them.
Otherwise, you need some structure around your code such as
boolean firstValueSeen = false;
int firstValue = -1;
for (…) {
…
int transientId = d_idGenerator.getNewId();
firstValueSeen = true;
firstValue = transientId

(Java) How do I make a database delete a stored value until the value has been stored more than 5 times?

I'm kinda trying to make a VERY basic replication of memory in a way.
Basically, I want my program to take in user input and forget it (delete it from database)after about 18 seconds, but remember it (permanently store it in database) if input is repeated 5 times or more.
Here's the code I have so far (It's a JavaFX program by the way):
TextField userText = new TextField();
Timeline time;
String message;
message = userText.getText();
ArrayList<String> memory = new ArrayList<>();
if(message.contains(message) && message.contains(" ") && !memory.contains(message)){
String[] splitMessage = message.split(" ");/*To split the sentence*/
for(int i = 0; i<splitMessage.length; i++)
memory.add(splitMessage[i]); /*To add the individual words of a sentence*/
memory.add(message); /*To add the sentence itself*/
time = new Timeline(new KeyFrame(Duration.millis(18000),
ae -> memory.remove(message)));
time.play();
}
So I have this so far and it works at storing data for 18 seconds. But I want it so the data is permanently stored into "memory" after the program has attempted to store the same message more than 5 times, whether consecutively or in random order.
Is there a way to do this?
Hope this made sense. I'm known for not wording questions properly haha.
Thanks in advance :).
This is my attempt at providing an additional layer of complexity to suffice your needs (if I understand them correctly).
I would replace:
ArrayList<String> memory = new ArrayList<>();
with
MemorySpace memorySpace = new MemorySpace();
The only problem that I see is the proper interpretation of:
!memory.contains(message);
It could be
memorySpace.isMemoryPermanent(message);
or
memorySpace.isMemoryActive(message);
Hopefully the API is clear enough for you to understand my intentions and how it could help in your situation. As I understand it a word is remembered permanently the first time but a sentence needs five time to become permanent.
public class MemorySpace {
private final Map<String, Memory> memorySpace;
public MemorySpace() {
this.memorySpace = new HashMap<>();
}
public void addWord(String word) {
Memory m = this.memorySpace.get(word);
if (m == null) {
this.memorySpace.put(word, new Memory(true, word))
}
}
public void addSentence(String sentence) {
Memory m = this.memorySpace.get(sentence);
if (m == null) {
this.memorySpace.put(sentence, new Memory(false, sentence))
}
else {
m.increaseSeenCount();
}
}
public boolean isMemoryPermanent(String workOrSentence) {
Memory m = this.memorySpace.get(wordOrSentence)
if (m != null) {
return m.isMemoryPermanent();
}
return false;
}
public boolean isMemoryActive(String workOrSentence) {
Memory m = this.memorySpace.get(wordOrSentence)
if (m != null) {
return m.isMemoryActive();
}
return false;
}
private class Memory {
private final boolean isWordMemory;
private final String wordOrSentence;
private int seenCount;
private long lastSeenAtMilliseconds;
Memory(boolean isWordMemory, String newWordOrSentence) {
this.isWordMemory = isWordMemory;
this.wordOrSentence = newWordOrSentence;
this.seenCount = 1;
this.lastSeenAtMilliseconds = System.currentTimeMillis();
}
boolean isWordMemory() {
return this.isWordMemory;
}
void increaseSeenCount() {
if (!this.isWordMemory) {
if (this.seenCount < 5) { // Stop overflow
this.seenCount++;
}
this.lastSeenAtMilliseconds = System.milliseconds();
}
}
void isMemoryPermanent() {
return this.isWordMemory || this.seenCount >= 5;
}
void isMemoryActive() {
return this.isWordMemory || this.isMemoryPermanent() || (System.currentTimeMillis() - this.lastSeenAtMilliseconds) < (18 * 1000);
}
}
}

I have to return a value from a function that is called multiple times and I am unable to do that

I am stuck.
The following function is supposed to return currVm, an integer. But if I make a return I will break the loop and next time when this function is called,the same process will begin again.
What shall I do, so that I continue from where I left off ? I tried making static variables but I that didn't help me.
#Override
public int getNextAvailableVm() {
Set<String> dataCenters = confMap.keySet();
for (String dataCenter : dataCenters) {
LinkedList<DepConfAttr> list = confMap.get(dataCenter);
Collections.sort(list, new MemoryComparator());
int size = list.size() - 1;
int count = 0;
while(size >= 0) {
DepConfAttr dca = (DepConfAttr)list.get(count);
int currVm = dca.getVmCount();
int c = 0;
while(c <= currVm) {
allocatedVm(currVm);
c++;
return currVm;
}
count++;
size--;
}
}
return 0;
}
The for-each loop assigns a new data center that acts as a key for the confMap.The list that I get as a value, is sorted.Then a loop is run till it escapes its size.Inside this while loop, another while loop is run from where a function named allocatedVm of the inherited class is called. A parameter named currVm is passed to it.
This is the variable that I need to return. What shall I do to return this variable ? I have to start from I left off. I mean the next call should appear to be the next step, whatever it was, while executing the loop.
Add List<Integer> object to your class, and change your method as follows:
private Iterator<Integer> availableVms = null;
#Override
public int getNextAvailableVm() {
if (availableVms != null) {
if (availableVms.hasNext()) {
return availableVms.next();
}
return 0;
}
List<Integer> tmp = new ArrayList<Integer>();
Set<String> dataCenters = confMap.keySet();
for (String dataCenter : dataCenters) {
LinkedList<DepConfAttr> list = confMap.get(dataCenter);
Collections.sort(list, new MemoryComparator());
int size = list.size() - 1;
int count = 0;
while(size >= 0) {
DepConfAttr dca = (DepConfAttr)list.get(count);
int currVm = dca.getVmCount();
int c = 0;
while(c <= currVm) {
allocatedVm(currVm);
c++;
tmp.add(currVm);
}
count++;
size--;
}
}
availableVms = tmp.iterator();
return availableVms.hasNext() ? availableVms.next() : 0;
}
The idea is to pre-generate the entire list, and store its iterator for future use. Before entering the method you check if the availableVms iterator has been prepared. If it has been prepared, grab the next item off of it if it's available; otherwise, return zero.
If the list has not been prepared yet, run your algorithm, and add the results to a temporary list tmp. Once the list is ready, grab its iterator, and use it for subsequent invocations.

Categories

Resources