Like Adrian mentioned in the comments, it's hard to know how to make your work method "work correctly" when we don't know how the way it's currently working is different from the way you want it to work.
That said, I do have an idea of what may be going wrong (and how to fix it).
First, answering the text of your question the purpose of keySet().contains(<something>) in the following snippet
for(WorkOrder i:newWorkOrder) {
if(resultMap.keyset().contains(i.ParentWorkOrderId)) {
WorkOrder wo = resultMap.get(i.ParentWorkOrderId);
i.related_address__c = wo.Related_Address__c;
// I've omitted the other lines for brevity
}
}
is to make sure that the WorkOrder wo variable inside the if block will never be null. The if statement checks to make sure that your map has an entry for i.ParentWorkOrderId (that the resulting Id exists as a key in the map) before it attempts to use the result of fetching the value in the map for that given key.
A simple example may make things a bit more clear
// This code can be run as anonymous apex through the developer console so that
// you can verify, for yourself, the assertions I'll be making.
// Declare a simple map that maps one integer to its negative
// What I'm doing here is one way to initialize a map
Map<Integer, Integer> testMap = new Map<Integer, Integer>{
1 => -1,
2 => -2
};
// A simple variable to store the result of a .get() from the map
Integer result;
result = testMap.get(1);
// map.containsKey() accomplishes the same thing as map.keySet().contains().
// using containsKey() is more compact, so it is generally preferred.
debug(testMap.containsKey(1)); // This will result in 'TRUE' being printed in the debug log
debug(result); // This will result in a '-1' being printed in the debug log
result = testMap.get(2);
debug(testMap.containsKey(2)); // This will result in 'TRUE' being printed in the debug log
debug(result); // This will result in a '-2' being printed in the debug log
// We did not make a map entry for the integer 3
result = testMap.get(3);
debug(testMap.containsKey(3)); // This will result in 'FALSE' being printed in the debug log
debug(result); // This will result in a 'null' being printed in the debug log
That's all well and good, but what does the if() block in your code actually guard against?
Let's expand the above example just a little more.
Map<Integer, Integer> testMap = new Map<Integer, Integer>{
1 => -1,
2 => -2
};
// A simple variable to store the result of a .get() from the map
Integer result = testMap.get(3);
// The format() method of the integer class returns a string representing the
// integer in the current user's locale.
// If integer i = 1000, i.format() would return '1,000' in US and UK locales
// but would return '1.000' in most other locales in the Eurozone (Germany, for example)
system.debug(result.format());
If you try to run that second code example, you'll get a null pointer exception.
Why? because 3 isn't a key in the map, and when we try to fetch the value for key 3 from the map, we get null as the result.
The system.debug line effectively becomes system.debug(null.format());. null doesn't have a format() method (it doesn't have any methods). Trying to use dot notation with null results in a null pointer exception.
Getting back to your code now
for(WorkOrder i:newWorkOrder) {
if(resultMap.containsKey(i.ParentWorkOrderId)) {
// because we're checking that i.ParentWorkOrderId exists as a key
// in resultMap, wo is guaranteed to not be null (well, as long as
// the value stored in the map itself isn't null).
// This means that wo.Related_Address__c is safe to execute (with one caveat).
WorkOrder wo = resultMap.get(i.ParentWorkOrderId);
i.related_address__c = wo.Related_Address__c;
// I've omitted the other lines for brevity (again)
}
}
So now you know what the purpose of that line is, we can move to getting your code to behave as expected.
Based on your code, it appears that you're depending on the behavior of before triggers to avoid the need to use DML to update the records you're passing in to copyWorkOrderAddress(). This does require a before trigger, and it also requires that you are passing in a list derived _directly from trigger.new (only changes made to the instances stored in trigger.new get auto-updated without DML).
Since you aren't running into a "record is read-only" error (at least, not yet or not that you've indicated), I can assume that this code is being run as part of a before trigger.
If your issue is that your child WorkOrder records aren't getting address values from the parent record, then you should check to see how you're calling your method.
// This should work, because we're directly using trigger.new, and SObjects/
// collections of SObjects are passed by reference (more or less, it's a bit more
// complicated than that in reality)
copyWorkOrderAddress(trigger.new);
// This should also work, because the loop variable 'wo' is a reference
// to the same instance of the work order record that is stored in trigger.new
List<WorkOrder> myList = new List<WorkOrder>();
for(WorkOrder wo :trigger.new){
if(someCondition){
myList.add(wo);
}
}
copyWorkOrderAddress(myList);
// This will not work, because the instance of the work order record we're
// storing in myOtherList is not a reference to the instance contained in
// trigger.new, it's a completely independent instance.
List<WorkOrder> myOtherList = new List<WorkOrder>();
for(WorkOrder wo :trigger.new){
if(someCondition){
myList.add(new WorkOrker(
Id = wo.Id,
ParentWorkOrderId = wo.ParentWorkOrderId
));
}
}
copyWorkOrderAddress(myList);
Hopefully I was able to identify the issue you're running into. If that isn't it, or you need more specific help, then posting your trigger and trigger handler would be helpful.
One last thing, that caveat I mentioned. As is, your current code doesn't check to see if i.ParentWorkOrderId is null before adding it to your list of Ids to query against. You should be safe in this case, but if you were to actually add null as a key to your map, you could still end up with a null pointer exception (or other fun, odd results could emerge).
When in doubt though, I would add relatedWOID.remove(null); after the loop that populates the relatedWOID set.